Почему имеет значение, где Toast производится в Android, если контекст один и тот же?

У меня есть устаревшее IntentService, которое пытается использовать сообщения Toast для отображения сообщений об ошибках. 1 Я бы хотел, чтобы сообщения отображаться и добавлять код, чтобы получить их в правильной теме. Простейшим изменением было бы передать в построенный объект Toast, а затем отобразить его в потоке пользовательского интерфейса. Тем не менее, тост отображается только в том случае, если я делаю его в опубликованном runnable, а не если я передаю предварительно сделанный 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();
        }
    });
}

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

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

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

Ответ 1

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

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

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

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