¿Cómo puedo mostrar los mensajes de Toast de un hilo?
¿Cómo puedo mostrar los mensajes de Toast de un hilo?
Respuestas:
Puede hacerlo llamando a un Activity's runOnUiThreadmétodo de su hilo:
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
}
});
Threadreferencia del objeto Activityen el Activity's onResume. Desarmarlo en Activity's onPause. Haz ambas cosas bajo un synchronizedcandado que tanto el Activitycomo el Threadrespeto.
Activityinstancia, puede usar una clase de ayuda simple en su lugar, consulte aquí: stackoverflow.com/a/18280318/1891118
MyActivity.this.runOnUiThread()funciona bien desde un interior Thread/ AsyncTask.
Me gusta tener un método en mi actividad llamado al showToastque puedo llamar desde cualquier lugar ...
public void showToast(final String toast)
{
runOnUiThread(() -> Toast.makeText(MyActivity.this, toast, Toast.LENGTH_SHORT).show());
}
Luego lo llamo con mayor frecuencia desde dentro MyActivityen cualquier hilo como este ...
showToast(getString(R.string.MyMessage));
Esto es similar a otras respuestas, sin embargo, actualizado para nuevas apis 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();
}
});
}
}
Un enfoque que funciona desde prácticamente cualquier lugar, incluso desde lugares donde no tienes una Activityo View, es tomar una Handleral 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.LENGTH_LONG).show();
}
});
}
La ventaja de este enfoque es que funciona con cualquiera Context, incluidos Servicey Application.
Como esto o esto , con un Runnableque 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();
}
A veces, tienes que enviar un mensaje desde otro Threadal hilo de la interfaz de usuario. Este tipo de escenario ocurre cuando no puede ejecutar operaciones de red / IO en el hilo de la interfaz de usuario.
El siguiente ejemplo maneja ese escenario.
Runnableel hilo de la interfaz de usuario. Así que publique su Runnablecontrolador enHandlerThreadRunnabley envíelo de vuelta al hilo de la interfaz de usuario y muestre un Toastmensaje.Solución:
HandlerThread:requestHandlerresponseHandlery handleMessagemétodo de anulaciónpostuna Runnabletarea enrequestHandlerRunnablede tareas, llame sendMessagearesponseHandlersendMessageinvocación de resultado de handleMessagein responseHandler.Messagey procesarlo, actualizar la interfaz de usuarioCó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:
manejarrthreads-y-por-qué-debería-usarlos-en-sus-aplicaciones-de-Android
handler.sendMessage();post()Método de llamadahandler.post();runOnUiThread()view.post() Puede utilizar Looperpara enviar un Toastmensaje. Vaya a este enlace para obtener 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 se llama en su hilo. Es posible que el contexto se Activity.getContext()obtenga del Activityque tienes que mostrar el brindis.
Hice este enfoque basado en la respuesta de 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();
}
});
}
Me funcionó bien.
Encontré 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.<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.
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ó.