Android: grillé dans un thread
Comment afficher Toast messages à partir d'un thread?
10 réponses
vous pouvez le faire en appelant un Activity
's runOnUiThread
méthode de votre fil:
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
}
});
j'aime avoir dans mon activité une méthode appelée showToast
que je peux appeler de n'importe où...
public void showToast(final String toast)
{
runOnUiThread(() -> Toast.makeText(MyActivity.this, toast, Toast.LENGTH_SHORT).show());
}
Je l'appelle donc le plus souvent de l'intérieur de MyActivity
sur n'importe quel fil comme celui-ci...
showToast(getString(R.string.MyMessage));
c'est similaire à d'autres réponses, cependant mis à jour pour les nouveaux API disponibles et beaucoup plus propre. En outre, ne suppose pas que vous êtes dans un contexte D'activité.
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();
}
});
}
}
Comme ce ou ce , avec un Runnable
qui montre que le Toast
.
À savoir,
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();
}
une approche qui fonctionne à peu près n'importe où, y compris des endroits où vous n'avez pas un Activity
ou View
, est de saisir un Handler
au fil principal et de montrer le toast:
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();
}
});
}
L'avantage de cette approche est qu'il fonctionne avec n'importe quel Context
, y compris Service
et Application
.
parfois, vous devez envoyer un message d'un autre Thread
au fil UI. Ce type de scénario se produit lorsque vous ne pouvez pas exécuter les opérations réseau/IO sur le thread UI.
ci-dessous l'exemple traite ce scénario.
- Vous avez Thread d'INTERFACE utilisateur
- vous devez démarrer L'opération IO et donc vous ne pouvez pas exécuter
Runnable
sur le thread UI. Alors postez votreRunnable
à handler surHandlerThread
- récupérez le résultat de
Runnable
et renvoyez-le au fil UI et affichez un messageToast
.
Solution:
- Créer un HandlerThread et il commence
- créer un Handler avec Looper de
HandlerThread
:requestHandler
- créer un Handler avec Looper à partir du fil principal:
responseHandler
et remplacerhandleMessage
méthode -
post
aRunnable
tâche surrequestHandler
- à l'Intérieur
Runnable
de la tâche, de l'appelersendMessage
surresponseHandler
- Ce
sendMessage
résultat de l'invocation de lahandleMessage
dansresponseHandler
. - Obtenir les attributs de la
Message
et de processus, mise à jour de l'INTERFACE utilisateur
Exemple de code:
/* 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);
}
articles utiles:
handlerthreads-et-pourquoi-vous-devrait-être-aide-dans-votre-android-apps
- Obtenir le Thread de l'INTERFACE utilisateur du Gestionnaire d'instance et d'utilisation
handler.sendMessage();
- Appel
post()
méthodehandler.post();
-
runOnUiThread()
-
view.post()
vous pouvez utiliser Looper
pour envoyer le message Toast
. Pour plus de détails, allez sur ce lien 151970920".
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();
}
et il est appelé dans votre fil. Le contexte peut être Activity.getContext()
le Activity
vous devez montrer le toast.
j'ai fait cette approche basée sur la réponse 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();
}
});
}
a bien Fonctionné pour moi.
j'ai rencontré le même problème ""
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.run(MainActivity.java:51)
at java.lang.Thread.run(Thread.java:764)
I/Process: Sending signal. PID: 4724 SIG: 9
Application terminated.
Avant: fonction oncrée
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show();
}
});
thread.start();
après: fonction oncrée
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getBaseContext(), "Thread", Toast.LENGTH_LONG).show();
}
});
ça a marché.