可以从工作线程调用NoticationManager.notify()吗?

我的问题更多的是什么是一个好的做法,而不是可能的:

  • 从工作线程调用NoticationManager.notify()是否是件好事?
  • 无论如何,系统是否在UI线程中执行它?

我总是试着记住,关于UI的东西应该在UI线程中执行,其余的在工作线程中执行,正如关于进程和线程的Android文档所build议的:

另外,Andoid UI工具包不是线程安全的。 所以,你不能从一个工作者线程操纵你的UI – 你必须从UI线程对你的用户界面进行所有的操作。 因此,Android的单线程模型只有两条规则:

  • 不要阻塞UI线程
  • 不要从UI线程之外访问Android UI工具包

然而,我对Android文档本身给出的一个例子感到惊讶( 关于通知的进展情况),其中一个持续的通知进度直接从工作者线程更新:

 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(); 

这就是为什么我想知道是否有必要在主线程上运行它,或者系统是否处理它。

谢谢你的帮助!

从工作者线程更新Notification是可以接受的,因为Notification不在你的应用程序的进程中,因此你不直接更新它的UI。 Notification在系统进程中维护, Notification的UI通过RemoteViews ( doc )更新,允许操作由自己以外的进程维护的视图层次结构。 如果您在这里查看Notification.Builder的源代码,您可以看到它最终构build了一个RemoteViews

如果你在这里查看RemoteViews的源代码,你会发现,当你操纵一个视图时,它实际上只是创build一个Action ( 源 )对象并将其添加到队列中进行处理。 一个Action是一个Parcelable ,它最终通过IPC发送到拥有Notification视图的进程,在那里它可以解压值,并按照指示更新视图…在它自己的UI线程上。

我希望澄清为什么可以在应用程序中更新工作线程的Notification