2011-12-06 6 views
4

私のユースケースは、(およそ)最初の起動時に次のようである:アンドロイドSTARTSERVICEは()UIスレッドに戻るには長い時間がかかる

  1. 活動が
  2. サービスが取得するサービスを開始し、データベース
  3. にデータを保存します
  4. サービスは、今、私は番目の間、プログレスバーを表示したい

意図

  • 活動データを表示して活動を通知しますeサービスがビジーです。問題は次のとおりです。

    startService(new Intent(getApplicationContext(), UpdateDataService.class));

    は、UIスレッドに「戻ってくる」に非常に長い時間がかかります。それは同期機能(またはnot?)のようです。サービスクラスが空の場合、startServiceコマンドはほとんど瞬時に処理されます。 UIスレッドはSericeがその作業を処理するのを待っているようですが、それはまったく意味がありません。私はUIスレッドでプログレスバーを表示している間にサービスを非同期タスクとして開始するように(愚かなように)始めようとしました。奇妙なことに、これは時々動作します。それ以外の場合は、サービスが動作している間に白い画面が表示され、その後は1ミリ秒のプログレスバーとUIが表示されます。

    私の質問:UIをブロックせずにサービスを開始するにはどうすればよいですか?ガイドトピックServicesから

    public class MyClass extends TabActivity { 
    private ProgressDialog pd; 
    
    @Override 
    public void onCreate(final Bundle savedInstanceState) { 
    
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
    
        Intent intent = null; 
    
        //building some tabs here, setting some text views.... 
    
        // starting service if does not exist yet 
        boolean serviceRunning = false; 
    
        final ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); 
        for (final RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 
         if ("aegir.mobile.UpdateDataService".equals(service.service.getClassName())) { 
          serviceRunning = true; 
          Log.i(MY_APP_TAG, "Service found."); 
         } 
        } 
        if (!serviceRunning) { 
         pd = ProgressDialog.show(this, "Loading...", "Setting up data.", true, false); 
         new StartServiceAsync().execute(""); 
        } 
    
    } 
    
    private final Handler handler = new Handler() { 
        @Override 
        public void handleMessage(final Message msg) { 
         pd.dismiss(); 
    
        } 
    }; 
    
    public class StartServiceAsync extends AsyncTask<String, Void, String> { 
    
        @Override 
        protected String doInBackground(final String... params) { 
         // starting service 
         startService(new Intent(getApplicationContext(), UpdateDataService.class)); 
         return null; 
        } 
    
        @Override 
        protected void onPostExecute(final String result) { 
         handler.sendEmptyMessage(0); 
         super.onPostExecute(result); 
        } 
    } 
    
  • 答えて

    1

    サービスのロジックを非同期タスクのdoInBackgroundメソッドに移動するだけでよいと思います。これは非同期タスクのためのもので、UIを操作するための簡単な作業を実行するための作業です。非同期タスクでサービスを呼び出すのは変ですが、その理由は何ですか?

    +0

    フム、呼び出し完了する時期。私はスレッドを開始すると、別のスレッドが並列に実行されることになると考えました。これは間違っているようです。私は、私のサービスの「仕事」を非同期タスクに入れようとします。ありがとうございました – Redfox

    9

    注意:サービスは、デフォルトでは、それが宣言されているアプリケーションと同じプロセスで、そのアプリケーションのメインスレッドで実行されます。そのため、ユーザーが同じアプリケーションのアクティビティとやりとりしている間にサービスが集中的またはブロック動作を実行した場合、そのサービスはアクティビティのパフォーマンスを低下させます。アプリケーションのパフォーマンスに影響を与えないようにするには、サービス内で新しいスレッドを開始する必要があります。

    これは、AsyncTaskからstartServiceを呼び出すだけで変わりません。

    1

    どちらの代わりにService昔ながらのIntentServiceを使用するか、あなたの仕事をするためにあなたのServiceからスレッドを開始し、AsyncTask自体にあなたの作業を行います。 AndroidのServiceは本質的に別のスレッドを使用していません(IntentServiceはその作業を行います)。

    にもかかわらず、今では、実際の仕事はあなたのUIスレッドで実行されているようで、AsyncTaskからあなたServiceを開始します。

    0

    お願いこのコードは、あなたが質問したことを行う簡単な方法です。

    @Override 
    public void onCreate(final Bundle savedInstanceState) { 
    
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
    
        Intent intent = null; 
        registerReceiver(dataUpdated, new IntentFilter("<FLAG>")); 
        //building some tabs here, setting some text views.... 
    
        // starting service if does not exist yet 
        boolean serviceRunning = false; 
    
        final ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); 
        for (final RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 
         if ("aegir.mobile.UpdateDataService".equals(service.service.getClassName())) { 
          serviceRunning = true; 
          Log.i(MY_APP_TAG, "Service found."); 
         } 
        } 
        if (!serviceRunning) { 
         pd = ProgressDialog.show(this, "Loading...", "Setting up data.", true, false); 
         startService(new Intent(getApplicationContext(), UpdateDataService.class)); 
        } 
    
    } 
    
    
    private BroadcastReceiver dataUpdated= new BroadcastReceiver() { 
        @SuppressLint("ShowToast") 
        @Override 
        public void onReceive(Context context, Intent intent) { 
         //<Your Process which you want when Service finishes a task > 
           pd.dismiss(); 
        } 
    }; 
    
    @Override 
    protected void onDestroy() { 
    
        unregisterReceiver(dataUpdated); 
    } 
    

    サービスであなたの仕事は本当のこのメソッド

    sendBroadcast(new Intent("<FLAG>")); 
    
    関連する問題