Android: Tostada en un hilo
-
01-10-2019 - |
Pregunta
¿Cómo puedo mostrar Toast mensajes de un hilo?
Solución
Puede hacerlo llamando al método Activity
de un runOnUiThread
de su hilo:
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
}
});
Otros consejos
Me gustaría tener un método en mi actividad denominada showToast
cual puedo llamar desde cualquier lugar ...
public void showToast(final String toast)
{
runOnUiThread(() -> Toast.makeText(MyActivity.this, toast, Toast.LENGTH_SHORT).show());
}
a continuación con mayor frecuencia lo llaman desde dentro MyActivity
sobre cualquier tema como este ...
showToast(getString(R.string.MyMessage));
Esto es similar a otras respuestas, sin embargo actualizada para las nuevas APIs disponibles y mucho más limpio. Además, no asuma que usted es 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();
}
});
}
}
Uno de los enfoques que funciona desde casi cualquier lugar, incluso desde lugares en los que no tienen un Activity
o View
, es para tomar un Handler
al hilo principal y mostrar la tostada:
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
, incluyendo Service
y Application
.
Al igual que este o este , con un Runnable
que muestra la Toast
.
Es decir,
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, usted tiene que enviar mensaje de otro Thread
al hilo de interfaz de usuario. Este tipo de situación se produce cuando no se puede ejecutar operaciones de red / IO en hilo de interfaz de usuario.
A continuación ejemplo mangos ese escenario.
- Usted tiene la interfaz de usuario de rosca
- Hay que empezar la operación IO y por lo tanto no se puede ejecutar
Runnable
el hilo de interfaz de usuario. Así publicar suRunnable
al manejador deHandlerThread
- Obtener el resultado de
Runnable
y enviarlo de nuevo a hilo de interfaz de usuario y mostrar un mensajeToast
.
Solución:
- HandlerThread e iniciarlo
- Crea un Handler con Looper de
HandlerThread
:requestHandler
- crear un controlador con Looper de Tema principal: método
responseHandler
yhandleMessage
anulación -
post
una tareaRunnable
enrequestHandler
- Dentro de la tarea
Runnable
,sendMessage
llamada enresponseHandler
- Este resultado
sendMessage
invocación dehandleMessage
enresponseHandler
. - Obtiene los atributos de la
Message
y procesarla, actualizar la interfaz de usuario
Código de ejemplo:
/* 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-y-qué-se-debe-ser-usando-les-en-su-android-aplicaciones
- recibir UI Thread ejemplo Handler y el uso
handler.sendMessage();
- método
post()
llamadahandler.post();
-
runOnUiThread()
-
view.post()
Se puede utilizar para enviar el mensaje Looper
Toast
. Ir a través de 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 le llama en el hilo. Contexto puede ser Activity.getContext()
llegar desde el Activity
usted tiene que demostrar la tostada.
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();
}
});
}
funcionado 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.<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 de: función onCreate
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show();
}
});
funcionó.