¿Cómo puedo mostrar los mensajes de Toast de un hilo?
Puedes hacerlo llamando al método runOnUiThread
una Activity
desde tu hilo:
activity.runOnUiThread(new Runnable() { public void run() { Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show(); } });
Me gusta tener un método en mi actividad llamado showToast
que pueda llamar desde cualquier lugar …
public void showToast(final String toast) { runOnUiThread(() -> Toast.makeText(MyActivity.this, toast, Toast.LENGTH_SHORT).show()); }
Entonces, con más frecuencia lo llamo desde MyActivity
en cualquier hilo como este …
showToast(getString(R.string.MyMessage));
Esto es similar a otras respuestas, sin embargo actualizado para las nuevas aplicaciones disponibles y mucho más limpio. Además, no asume que estás en un contexto de actividad.
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(); } }); } }
Me gusta esto o esto , con un Runnable
que muestra el Toast
. A saber,
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(); }
En ocasiones, debe enviar un mensaje de otro Thread
al Thread
de interfaz de usuario. Este tipo de escenario ocurre cuando no puede ejecutar las operaciones de red / IO en el hilo de la interfaz de usuario.
El ejemplo siguiente maneja ese escenario.
Runnable
iniciar la operación IO y, por lo tanto, no puede ejecutar Runnable
en el hilo de UI. Runnable
tu Runnable
en handler en HandlerThread
Runnable
y envíelo de nuevo al hilo de la interfaz de usuario y muestre un mensaje de Toast
. Solución:
HandlerThread
con Looper desde HandlerThread
: requestHandler
responseHandler
y anule el método handleMessage
post
una tarea requestHandler
en requestHandler
Runnable
, llame a sendMessage
en responseHandler
sendMessage
resultado sendMessage
de handleMessage
en responseHandler
. Message
y procesarlo, actualizar la interfaz de usuario Código de muestra:
/* 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); }
Artículos útiles:
handlerthreads-and-why-you-be-be-usand-them-in-your-android-apps
android-looper-handler-handlerthread-i
Un enfoque que funciona desde casi cualquier lugar, incluso desde lugares donde no tiene una Activity
o View
, es agarrar un Handler
al hilo principal y mostrar el brindis:
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.DURATION_LONG).show(); } }); }
La ventaja de este enfoque es que funciona con cualquier Context
, incluido el Service
y la Application
.
handler.sendMessage();
post()
método handler.post();
runOnUiThread()
view.post()
Puede usar Looper
para enviar un mensaje de Toast
. Visita este enlace para más detalles.
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(); }
y es llamado en tu hilo. El contexto puede ser Activity.getContext()
obteniendo de la Activity
que tiene que mostrar el brindis.
Hice este enfoque basado en la respuesta 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(); } }); }
Funcionó bien para mí
Me encontré con el mismo problema:
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.(Toast.java:393) at android.widget.Toast. (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.
Antes: función onCreate
Thread thread = new Thread(new Runnable() { @Override public void run() { Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show(); } }); thread.start();
Después: función onCreate
runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show(); } });
funcionó.