【问题标题】:Can NoticationManager.notify() be called from a worker thread?可以从工作线程调用 NoticationManager.notify() 吗?
【发布时间】:2013-03-09 22:41:42
【问题描述】:

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

  • 从工作线程调用NoticationManager.notify() 是不是一件好事?
  • 系统是否在 UI 线程中执行它?

我总是尽量记住,关于 UI 的东西应该在 UI 线程中执行,其余的在工作线程中执行,正如 Android 文档关于 Processes And Threads 所建议的那样:

此外,Andoid UI 工具包不是线程安全的。所以,你必须 不要从工作线程操作你的 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();

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

感谢您的帮助!

【问题讨论】:

    标签: android multithreading notifications android-notifications


    【解决方案1】:

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

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

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

    【讨论】:

    • 您好,阅读您的回答,我尝试在 SyncAdapter (AbstractThreadedSyncAdapter) 中创建通知。通知工作正常,但我无法取消它们。与在 ui 线程中显示相比,是否有任何限制或差异?示例要点:gist.github.com/mauron85/f8c40096643f5bb08fcb7d77ff30e4b1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 2021-08-10
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 2012-11-24
    相关资源
    最近更新 更多