Подтвердить что ты не робот

Может ли NoticationManager.notify() вызываться из рабочего потока?

Мой вопрос больше о том, что является хорошей практикой, чем то, что возможно:

  • Хорошо ли вызывать NoticationManager.notify() из рабочего потока?
  • Выполняет ли система в потоке пользовательского интерфейса или нет?

Я всегда стараюсь иметь в виду, что материал, связанный с пользовательским интерфейсом, должен выполняться в потоке пользовательского интерфейса, а остальное - в рабочих потоках, как это предлагает документ Android о Processes And Threads:

Кроме того, инструментарий Andoid UI не является потокобезопасным. Итак, вы должны не манипулируйте своим пользовательским интерфейсом из рабочего потока - вы должны делать все манипуляции с пользовательским интерфейсом из потока пользовательского интерфейса. Таким образом, это просто два правила для модели с одним потоком в Android:

  • Не блокируйте поток пользовательского интерфейса
  • Не обращайтесь к инструментарию 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();

Вот почему мне интересно, нужно ли вообще запускать его в основном потоке, или если система позаботится об этом.

Спасибо за вашу помощь!

4b9b3361

Ответ 1

Допустимо обновлять Notification из рабочего потока, потому что Notification не работает в вашем процессе приложения и, следовательно, вы не обновляете его интерфейс напрямую. Уведомление поддерживается в системном процессе, а пользовательский интерфейс Notification обновляется через RemoteViews (doc), что позволяет манипулировать иерархией представлений, которая поддерживается другим процессом, чем ваш собственный. Если вы посмотрите на источник Notification.Builder здесь, вы увидите, что он в конечном итоге создает RemoteViews.

И если вы посмотрите на источник RemoteViews здесь, вы увидите, что при манипулировании просмотром на самом деле просто создается Action (источник) и добавить его в очередь, подлежащую обработке. Action - это Parcelable, который в конечном итоге отправляется через IPC в процесс, которому принадлежит представление Notification, где он может распаковать значения и обновить представление, как указано... на его собственном потоке пользовательского интерфейса.

Я надеюсь, что это пояснит, почему это нормально обновлять Notification из рабочего потока в вашем приложении.