可以从工作线程调用 NotificationManager.notify() 吗? [英] Can NoticationManager.notify() be called from a worker thread?

查看:13
本文介绍了可以从工作线程调用 NotificationManager.notify() 吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题更多的是关于什么是好的做法而不是什么是可能的:

My question is more about what is a good practice than what is possible:

  • 从工作线程调用 NotificationManager.notify() 是好事吗?
  • 系统是否会在 UI 线程中执行它?
  • Is it a good thing to call NoticationManager.notify() from a worker thread?
  • Does the system execute it in the UI thread anyway or not?

我总是尽量记住,关于 UI 的内容应该在 UI 线程中执行,其余的在工作线程中执行,正如关于 进程和线程:

I always try to keep in mind that stuff concerning the UI should be executed in the UI thread and the rest in worker threads, as suggested by the Android doc about Processes And Threads:

此外,Andoid UI 工具包不是线程安全的.所以,你必须不要从工作线程操作你的 UI——你必须做所有的事情从 UI 线程对您的用户界面进行操作.因此,有Android 的单线程模型只是两个规则:

Additionally, the Andoid UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread. Thus, there are simply two rules to Android's single thread model:

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

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

HOWEVER, I was surprised by an example given by the Android doc itself (about showing progress in Notifications), where an ongoing notification progress was updated directly from a worker thread:

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

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

That's why I'm wondering if it is actually necessary to run it on the main thread, or if the system takes care of it.

感谢您的帮助!

推荐答案

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

It is acceptable to update a Notification from a worker thread because the Notification does not live in your application's process and hence you are not updating its UI directly. The Notification is maintained in a system process, and the Notification's UI is updated through RemoteViews (doc), which allows the manipulation of a view hierarchy that is maintained by a process other than your own. If you look at the source for Notification.Builder here you can see that it is ultimately building a RemoteViews.

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

And if you look at the source for RemoteViews here you'll see that when you manipulate a view it is really just creating an Action (source) object and adding it to a queue to be processed. An Action is a Parcelable that is ultimately sent via IPC to the process that owns the Notification's view, where it can unpack the values and update the view as indicated... on it's own UI thread.

我希望阐明为什么可以从应用程序中的工作线程更新 Notification.

I hope that clarifies why it is OK to update a Notification from a worker thread in your application.

这篇关于可以从工作线程调用 NotificationManager.notify() 吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆