Как вы показываете тост из фоновой беседы на Android?

Ответы:

246

Вы можете сделать это путем вызова Activity«S runOnUiThreadметод из вашего потока:

activity.runOnUiThread(new Runnable() {
    public void run() {
        Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
    }
});
Лаури Лехтинен
источник
Не уверен, что понимаю, как это сделать. У меня есть мой существующий public void run (). Я пробовал поместить туда этот код. Я знаю, что это неправильно, потому что это не сработало, но я действительно застрял.
SwimBikeRun
14
"Активность" передается не-пользовательскому потоку в его конструкторе? Как правильно получить объект действия, который вы используете, из отдельного потока?
snapfractalpop
Установите на Threadссылку объекта к Activityв Activity«с onResume. Отозвать его в Activity«с onPause. Делайте то и другое под synchronizedзамком, который соблюдают Activityи Threadуважают.
JohnnyLambada
5
иногда нет доступа к Activityэкземпляру, вместо этого вы можете использовать простой вспомогательный класс, см. здесь: stackoverflow.com/a/18280318/1891118
Алексей К.
5
Я обычно обнаружил, что MyActivity.this.runOnUiThread()это прекрасно работает внутри внутреннего Thread/ AsyncTask.
Энтони Аткинсон
62

Мне нравится иметь в моей деятельности метод, showToastкоторый я могу вызывать откуда угодно ...

public void showToast(final String toast)
{
    runOnUiThread(() -> Toast.makeText(MyActivity.this, toast, Toast.LENGTH_SHORT).show());
}

Затем я чаще всего вызываю его изнутри MyActivityв любом потоке, подобном этому ...

showToast(getString(R.string.MyMessage));
Mjaggard
источник
3
Спасибо, сейчас я добавляю это большинство занятий.
Джин Майерс
1
Для TOAST всегда используйте контекст приложения, а не контекст действия!
Юша Алеайуб
1
@YoushaAleayoub почему?
OneWorld
1
@OneWorld, доказательства: 1. Для всплывающего сообщения Google Dev Guide использует контекст приложения и явно указывает использовать его. 2- stackoverflow.com/a/4128799/1429432 3- stackoverflow.com/a/10347346/1429432 4- groups.google.com/d/msg/android-developers/3i8M6-wAIwM/…
Юша Алеайуб
@YoushaAleayoub В предоставленных вами ссылках много дискуссий и предположений. Например, RomainGuy утверждает, что в вашем доказательстве нет утечки памяти. 4. Некоторые ссылки относятся к раннему периоду Android в 2009 году. Также люди говорят в других ссылках, что вы можете использовать оба контекста. Деятельность и применение. Может быть, у вас есть более современные доказательства, основанные на доказательствах? У вас есть ссылка на 1?
OneWorld,
28

Это похоже на другие ответы, но обновлено для новых доступных API и намного чище. Кроме того, не предполагается, что вы находитесь в контексте деятельности.

public class MyService extends AnyContextSubclass {

    public void postToastMessage(final String message) {
        Handler handler = new Handler(Looper.getMainLooper());

        handler.post(new Runnable() {

            @Override
            public void run() {
                Toast.makeText(getContext(), message, Toast.LENGTH_LONG).show();
            }
        });
    }
}
ChrisCM
источник
Когда контекст, который у вас есть, не является деятельностью, это идеальный ответ. Большое спасибо!
francas
17

Один из подходов, который работает практически из любого места, в том числе из мест, где у вас нет Activityили View, - это захватить Handlerосновной поток и показать тост:

public void toast(final Context context, final String text) {
  Handler handler = new Handler(Looper.getMainLooper());
  handler.post(new Runnable() {
    public void run() {
      Toast.makeText(context, text, Toast.LENGTH_LONG).show();
    }
  });
}

Преимущество такого подхода в том, что он работает с любыми Context, в том числе Serviceи Application.

Майк Ларен
источник
10

Как то или это , с тем, Runnableчто показывает Toast. А именно,

Activity activity = // reference to an Activity
// or
View view = // reference to a View

activity.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        showToast(activity);
    }
});
// or
view.post(new Runnable() {
    @Override
    public void run() {
        showToast(view.getContext());
    }
});

private void showToast(Context ctx) {
    Toast.makeText(ctx, "Hi!", Toast.LENGTH_SHORT).show();
}
Янченко
источник
6

Иногда вам нужно отправить сообщение из другого Threadпотока пользовательского интерфейса. Этот тип сценария возникает, когда вы не можете выполнять операции сети / ввода-вывода в потоке пользовательского интерфейса.

Пример ниже обрабатывает этот сценарий.

  1. У вас есть поток пользовательского интерфейса
  2. Вы должны начать операцию ввода-вывода, и, следовательно, вы не можете работать Runnableв потоке пользовательского интерфейса. Так что опубликуйте свой Runnableобработчик наHandlerThread
  3. Получите результат Runnableи отправьте его обратно в поток пользовательского интерфейса и покажите Toastсообщение.

Решение:

  1. Создайте HandlerThread и запустите его
  2. Создайте обработчик с помощью Looper из HandlerThread:requestHandler
  3. Создайте обработчик с помощью Looper из основного потока: responseHandlerи переопределите handleMessageметод
  4. postRunnableзадача поrequestHandler
  5. Внутри Runnableзадача, вызов sendMessageнаresponseHandler
  6. Это sendMessageрезультат вызова handleMessagein responseHandler.
  7. Получить атрибуты из Messageи обработать, обновить UI

Образец кода:

    /* Handler thread */

    HandlerThread handlerThread = new HandlerThread("HandlerThread");
    handlerThread.start();
    Handler requestHandler = new Handler(handlerThread.getLooper());

    final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Runnable on HandlerThread is completed and got result:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

    for ( int i=0; i<5; i++) {
        Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                try {

                    /* Add your business logic here and construct the 
                       Messgae which should be handled in UI thread. For 
                       example sake, just sending a simple Text here*/

                    String text = "" + (++rId);
                    Message msg = new Message();

                    msg.obj = text.toString();
                    responseHandler.sendMessage(msg);
                    System.out.println(text.toString());

                } catch (Exception err) {
                    err.printStackTrace();
                }
            }
        };
        requestHandler.post(myRunnable);
    }

Полезные статьи:

обработчики потоков-и-почему-вам-следует-использовать-их-в-ваших-андроид-приложениях

андроид-обработчик-обработчик-обработчик-поток-я

Равиндра бабу
источник
5
  1. Получить экземпляр обработчика потока пользовательского интерфейса и использовать handler.sendMessage();
  2. post()Метод вызоваhandler.post();
  3. runOnUiThread()
  4. view.post()
Кервин Вы
источник
3

Вы можете использовать Looperдля отправки Toastсообщения. Для получения более подробной информации перейдите по этой ссылке .

public void showToastInThread(final Context context,final String str){
    Looper.prepare();
    MessageQueue queue = Looper.myQueue();
    queue.addIdleHandler(new IdleHandler() {
         int mReqCount = 0;

         @Override
         public boolean queueIdle() {
             if (++mReqCount == 2) {
                  Looper.myLooper().quit();
                  return false;
             } else
                  return true;
         }
    });
    Toast.makeText(context, str,Toast.LENGTH_LONG).show();      
    Looper.loop();
}

и это называется в вашей ветке. Контекст может быть Activity.getContext()получен из-за Activityтого, что вы должны показать тост.

Винодж Джон Хосан
источник
2

Я сделал этот подход на основе ответа mjaggard:

public static void toastAnywhere(final String text) {
    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
        public void run() {
            Toast.makeText(SuperApplication.getInstance().getApplicationContext(), text, 
                    Toast.LENGTH_LONG).show();
        }
    });
}

Хорошо сработало для меня.

Анджело Полотто
источник
0

Я столкнулся с той же проблемой :

E/AndroidRuntime: FATAL EXCEPTION: Thread-4
              Process: com.example.languoguang.welcomeapp, PID: 4724
              java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare()
                  at android.widget.Toast$TN.<init>(Toast.java:393)
                  at android.widget.Toast.<init>(Toast.java:117)
                  at android.widget.Toast.makeText(Toast.java:280)
                  at android.widget.Toast.makeText(Toast.java:270)
                  at com.example.languoguang.welcomeapp.MainActivity$1.run(MainActivity.java:51)
                  at java.lang.Thread.run(Thread.java:764)
I/Process: Sending signal. PID: 4724 SIG: 9
Application terminated.

Раньше: функция onCreate

Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show();
    }
});
thread.start();

После: функция onCreate

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show();
    }
});

это сработало.

Лангогуанг
источник