37

我的問題是更多的是比什麼是可能的一個很好的做法:可以從工作線程調用NoticationManager.notify()嗎?

  • 這是個好東西叫從一個工作線程NoticationManager.notify()
  • 無論如何,系統是否在UI線程中執行它?

我總是儘量記住有關UI應該在UI線程和工作線程其餘被執行,被Android文檔的建議有關Processes And Threads的東西:

此外, Andoid UI工具包不是線程安全的。因此,您必須不要從工作線程操縱您的用戶界面 - 您必須從UI線程對您的用戶界面進行所有 操作。因此,有 只是兩個規則Android的單線程模型:

  • 不要阻塞UI線程
  • 不要從UI線程之外

無論其訪問Android的UI工具包,我對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是可以接受的,因爲Notification不在您的應用程序的進程中,因此您不直接更新其UI。通知在系統進程中維護,Notification的用戶界面通過RemoteViewsdoc)進行更新,該操作允許操作由您自己以外的進程維護的視圖層次結構。如果您查看Notification.Builder​​的來源,您可以看到它最終構建了一個RemoteViews

如果你看看源RemoteViewshere,你會看到,當你操縱視圖它實際上只是創建一個Actionsource)對象並將其添加到隊列中進行處理。 Action是一個Parcelable,它最終通過IPC發送到擁有Notification的視圖的進程,在該進程中它可以解壓縮值並按照指示更新視圖...在它自己的UI線程上。

我希望澄清爲什麼可以從應用程序中的工作線程更新Notification

+1

這正是我一直在尋找的,非常感謝! – Joffrey 2013-04-04 12:44:48

+0

您好,我已經嘗試在SyncAdapter(AbstractThreadedSyncAdapter)中創建通知。通知工作正常,但我不能讓它們取消。與在UI線程中顯示相比,是否有任何限制或差異?例如: https://gist.github.com/mauron85/f8c40096643f5bb08fcb7d77ff30e4b1 – mauron85 2016-07-21 09:42:49

相關問題