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

我的问题更多是关于什么是好的实践,而不是可能的:

  • 从辅助线程调用NoticationManager.notify()是件好事吗?
  • 系统是否仍在UI线程中执行它?

我总是要谨记,有关UI的内容应在UI线程中执行,其余部分应在工作线程中执行,如Android关于流程和线程的文档所建议的那样:

此外,Andoid UI工具包也不是线程安全的。 所以,你必须 不能通过辅助线程来操作您的UI,您必须做所有 从UI线程对用户界面进行操作。 因此, 仅仅是Android单线程模型的两个规则:

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

但是,我对Android文档本身给出的一个示例感到惊讶(关于在Notifications中显示进度),其中正在进行的通知进度是直接从worker线程更新的:

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

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

谢谢你的帮助!

1个解决方案
79 votes

从工作线程更新Notification是可以接受的,因为Notification不在应用程序的进程中,因此您没有直接更新其UI。 通知是在系统进程中维护的,并且通过RemoteViews(doc)更新了Notification的UI,该UI允许操纵由您自己以外的进程维护的视图层次结构。 如果在这里查看Notification的来源,您会看到它最终正在构建Action

而且,如果您在这里查看Notification的源代码,您会看到,当您操作视图时,它实际上只是创建Action(源代码)对象并将其添加到要处理的队列中。 ActionParcelable,最终通过IPC发送到拥有Notification的视图的进程,在该进程中,它可以解包值并按照自己的UI线程上的指示更新视图。

我希望可以阐明为什么可以从应用程序中的辅助线程更新Notification的原因。

Brett Duncavage answered 2020-08-01T15:43:26Z
translate from https://stackoverflow.com:/questions/15530293/can-noticationmanager-notify-be-called-from-a-worker-thread