37

私の質問は可能であるものよりも良い方法は何かについての詳細です:NotifierManager.notify()をワーカースレッドから呼び出すことはできますか?

  • ワーカースレッドからNoticationManager.notify()を呼び出すことは良いことですか?
  • システムはUIスレッドでシステムを実行しますかどうかを確認します。

私は常にUIに関する詰め込むことに注意してくださいしてみてくださいProcesses And Threads程度のAndroidのdocにより示唆されるように、UIスレッドとワーカースレッドでの残りの部分で実行する必要があります。

また、 Andoid UIツールキットはスレッドセーフではありません。そのため、 ワーカースレッドからUIを操作しないでください。すべての操作をUIスレッドからユーザーインターフェイスに行う必要があります。

もつともUIスレッドの外からAndroidのUIツールキットにはアクセスしないでくださいUIスレッドをブロックしないでください。このように、そこに は、Androidのシングルスレッドモデルには2つのルールは単純です私は、Androidのドキュメントそのもの(about showing progress in Notifications)の例で驚いていました。進行中の通知の進行状況はワーカースレッドから直接更新されていました。

mNotifyManager = 
     (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
mBuilder = new NotificationCompat.Builder(this); 
mBuilder.setContentTitle("Picture Download") 
    .setContentText("Download in progress") 
    .setSmallIcon(R.drawable.ic_notification); 
// Start a lengthy operation in a background thread 
new Thread(
    new Runnable() { 
     @Override 
     public void run() { 
      int incr; 
      // Do the "lengthy" operation 20 times 
      for (incr = 0; incr <= 100; incr+=5) { 
        // Sets the progress indicator to a max value, the 
        // current completion percentage, and "determinate" 
        // state 
        mBuilder.setProgress(100, incr, false); 
        // Displays the progress bar for the first time. 
        mNotifyManager.notify(0, mBuilder.build()); 
         // Sleeps the thread, simulating an operation 
         // that takes time 
         try { 
          // Sleep for 5 seconds 
          Thread.sleep(5*1000); 
         } catch (InterruptedException e) { 
          Log.d(TAG, "sleep failure"); 
         } 
      } 
      // When the loop is finished, updates the notification 
      mBuilder.setContentText("Download complete") 
      // Removes the progress bar 
        .setProgress(0,0,false); 
      mNotifyManager.notify(ID, mBuilder.build()); 
     } 
    } 
// Starts the thread by calling the run() method in its Runnable 
).start(); 

これは、実際にメインスレッド上で実行する必要があるのか​​、システムがそれを処理するのか不思議です。

ありがとうございました!

答えて

65

Notificationがアプリケーションのプロセスに存在しないため、UIを直接更新していないため、Notificationをワーカースレッドから更新することは可能です。通知はシステムプロセスで維持され、NotificationのUIはRemoteViewsdoc)によって更新されます。これにより、自分以外のプロセスによって維持されるビュー階層の操作が可能になります。 Notification.Builder​​のソースを見ると、最終的にRemoteViewsが作成されていることがわかります。

そして、あなたはRemoteViewshereのソースを見れば、あなたはそれが本当にただActionsource)オブジェクトを作成し、処理するキューに追加されたビューを操作したときにことがわかります。 ActionParcelableで、最終的にIPC経由でNotificationのビューを所有しているプロセスに送信されます。このビューでは、値をアンパックして指定されたとおりにビューを更新できます。

あなたのアプリケーションのワーカースレッドからNotificationを更新するのがなぜよいかを明確にしたいと思います。

+1

これは私が探していたものです。ありがとうございます! – Joffrey

+0

あなたの答えを読んで、私はSyncAdapter(AbstractThreadedSyncAdapter)で通知を作成しようとしました。通知をキャンセルすることはできません。 uiスレッドで表示するのに比べて制限や相違はありますか? 例を表示: https://gist.github.com/mauron85/f8c40096643f5bb08fcb7d77ff30e4b1 – mauron85

関連する問題