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

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

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

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

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

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

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