Какая разница, где сделан Toast в Android, если контекст тот же?

У меня есть устаревшая версия IntentService, которая пытается использовать всплывающие сообщения для отображения сообщений об ошибках.1 Я хочу, чтобы сообщения отображались, и добавил код, чтобы они попадали в нужную ветку. Самым простым изменением было бы передать созданный объект Toast, а затем отобразить его в потоке пользовательского интерфейса. . Однако тост отображается только в том случае, если я создал его в опубликованном исполняемом файле, а не в том случае, если я передаю готовый Toast.

Это работает:

@Override
protected void onHandleIntent(Intent intent) {
    showToast("Error", Toast.LENGTH_LONG);
}

private void showToast(final String msg, final int duration) {
    new Handler(getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            // Make and show the toast in the posted runnable
            Toast.makeText(getApplicationContext(), msg, duration).show();
        }
    });
}

Это не работает:

@Override
protected void onHandleIntent(Intent intent) {
    // Make the toast here
    Toast myToast = Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_LONG);
    showToast(myToast);
}

private void showToast(final Toast toast) {
    new Handler(getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            // Show the toast here
            toast.show();
        }
    });
}

В обоих случаях контекст — это контекст приложения, и я не увидел в исходниках ничего, что заставило бы одну версию работать, а другую — нет. Вместо этого последний имеет те же проблемы, как если бы Toast отображался непосредственно в IntentService: «Handler (android.os.Handler) {...} отправляет сообщение обработчику в мертвом потоке», Toast не исчезает и т. д.

Почему всплывающее уведомление должно быть создано в основной ветке, а не просто показано там?

1. Наследие = я не думаю, что отображение сообщений об ошибках в тостах — это отличный пользовательский интерфейс, и я не думаю, что сервисы, отображающие сообщения пользователям напрямую, — хорошая идея, но это код, который мне передали, и я хотел бы сделать его таким маленьким. немного лучше.


person blahdiblah    schedule 05.03.2014    source источник


Ответы (1)


Во втором опубликованном вами коде Toast создается в фоновом потоке, в котором настроены петлитель и обработчик (это точка IntentService).

Тост использует цикл текущего потока для создания обработчика, но как только IntentService завершает обработку работы в onHandleIntent, он останавливается (если нет других намерений для обработки), уничтожая поток, на который опирается ваш обработчик Toast.

строка 327: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/widget/Toast.java

Создание всплывающего уведомления в runnable работает, потому что в этот момент текущий поток является потоком пользовательского интерфейса.

person FunkTheMonk    schedule 07.03.2014
comment
Это похоже на источник проблемы. Интересно, они делают обработчик там, а не ближе к тому месту, где он нужен. Похоже на ненужное усложнение для того, что на тот момент было очень простым объектом. - person blahdiblah; 10.03.2014