Impossible de créer un gestionnaire à l’intérieur du thread qui n’a pas appelé Looper.prepare ()

Que signifie l’exception suivante? Comment puis-je le réparer?

Ceci est le code:

Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT); 

C’est l’exception:

 java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() at android.os.Handler.(Handler.java:121) at android.widget.Toast.(Toast.java:68) at android.widget.Toast.makeText(Toast.java:231) 

Vous l’appelez d’un thread de travail. Vous devez appeler Toast.makeText() (et la plupart des autres fonctions traitant de l’interface utilisateur) depuis le thread principal. Vous pouvez utiliser un gestionnaire, par exemple.

Recherchez la communication avec le thread d’interface utilisateur dans la documentation. En un mot:

 // Set this up in the UI thread. mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message message) { // This is where you do your work in the UI thread. // Your worker tells you in the message what to do. } }; void workerThread() { // And this is how you call it from the worker thread: Message message = mHandler.obtainMessage(command, parameter); message.sendToTarget(); } 

Autres options:

Vous pouvez utiliser une AsyncTask , qui fonctionne bien pour la plupart des choses fonctionnant en arrière-plan. Il a des crochets que vous pouvez appeler pour indiquer la progression et quand cela est fait.

Vous pouvez également utiliser Activity.runOnUiThread () .

Vous devez appeler Toast.makeText(...) partir du thread de l’interface utilisateur:

 activity.runOnUiThread(new Runnable() { public void run() { Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show(); } }); 

Ceci est copié-collé à partir d’ une autre réponse SO (dupliquée) .

MISE À JOUR – 2016

La meilleure solution consiste à utiliser RxAndroid (liaisons spécifiques pour RxJava ) pour que le P de MVP prenne en charge les données.

Commencez par retourner Observable partir de votre méthode existante.

 private Observable getObservableItems() { return Observable.create(subscriber -> { for (PojoObject pojoObject: pojoObjects) { subscriber.onNext(pojoObject); } subscriber.onCompleted(); }); } 

Utilisez cette observable comme ceci –

 getObservableItems(). subscribeOn(Schedulers.io()). observeOn(AndroidSchedulers.mainThread()). subscribe(new Observer () { @Override public void onCompleted() { // Print Toast on completion } @Override public void onError(Throwable e) {} @Override public void onNext(PojoObject pojoObject) { // Show Progress } }); } 

————————————————– ————————————————– ——————————

Je sais que je suis un peu en retard mais voilà. Android fonctionne essentiellement sur deux types de thread, à savoir le thread d’interface utilisateur et le thread d’arrièreplan . Selon la documentation Android –

N’accédez pas à la boîte à outils d’interface utilisateur Android en dehors du thread d’interface utilisateur pour résoudre ce problème, Android offre plusieurs façons d’accéder au thread d’interface utilisateur à partir d’autres threads. Voici une liste de méthodes pouvant vous aider:

 Activity.runOnUiThread(Runnable) View.post(Runnable) View.postDelayed(Runnable, long) 

Maintenant, il existe différentes méthodes pour résoudre ce problème.

Je vais l’expliquer par exemple de code:

runOnUiThread

 new Thread() { public void run() { myactivity.this.runOnUiThread(new Runnable() { public void run() { //Do your UI operations like dialog opening or Toast here } }); } }.start(); 

LOOPER

Classe utilisée pour exécuter une boucle de message pour un thread. Les threads par défaut ne sont pas associés à une boucle de message. pour en créer un, appelez prepare () dans le thread qui doit exécuter la boucle, puis loop () pour qu’il traite les messages jusqu’à ce que la boucle soit arrêtée.

 class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } } 

AsyncTask

AsyncTask vous permet d’effectuer un travail asynchrone sur votre interface utilisateur. Il effectue les opérations de blocage dans un thread de travail, puis publie les résultats sur le thread d’interface utilisateur, sans que vous ayez à gérer vous-même les threads et / ou les gestionnaires.

 public void onClick(View v) { new CustomTask().execute((Void[])null); } private class CustomTask extends AsyncTask { protected Void doInBackground(Void... param) { //Do some work return null; } protected void onPostExecute(Void param) { //Print Toast or open dialog } } 

Manutentionnaire

Un gestionnaire vous permet d’envoyer et de traiter des objects Message et Runnable associés à un MessageQueue d’un thread.

 Message msg = new Message(); new Thread() { public void run() { msg.arg1=1; handler.sendMessage(msg); } }.start(); Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { if(msg.arg1==1) { //Print Toast or open dialog } return false; } }); 

Essayez ceci lorsque vous voyez runtimeException à cause de Looper qui n’a pas été préparé avant le gestionnaire.

 Handler handler = new Handler(Looper.getMainLooper()); handler.postDelayed(new Runnable() { @override void run() { // Run your task here } }, 1000 ); 

J’ai rencontré le même problème et voici comment je l’ai corrigé:

 private final class UIHandler extends Handler { public static final int DISPLAY_UI_TOAST = 0; public static final int DISPLAY_UI_DIALOG = 1; public UIHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { switch(msg.what) { case UIHandler.DISPLAY_UI_TOAST: { Context context = getApplicationContext(); Toast t = Toast.makeText(context, (Ssortingng)msg.obj, Toast.LENGTH_LONG); t.show(); } case UIHandler.DISPLAY_UI_DIALOG: //TBD default: break; } } } protected void handleUIRequest(Ssortingng message) { Message msg = uiHandler.obtainMessage(UIHandler.DISPLAY_UI_TOAST); msg.obj = message; uiHandler.sendMessage(msg); } 

Pour créer le UIHandler, vous devez effectuer les opérations suivantes:

  HandlerThread uiThread = new HandlerThread("UIHandler"); uiThread.start(); uiHandler = new UIHandler((HandlerThread) uiThread.getLooper()); 

J’espère que cela t’aides.

Raison de l’erreur:

Les threads de travail sont conçus pour effectuer des tâches en arrière-plan et vous ne pouvez rien afficher sur l’interface utilisateur dans un thread de travail, sauf si vous appelez la méthode comme runOnUiThread . Si vous essayez d’afficher quelque chose sur le thread d’interface utilisateur sans appeler runOnUiThread, il y aura une java.lang.RuntimeException .

Donc, si vous êtes dans une activity mais que vous appelez Toast.makeText() depuis le thread de travail, procédez comme Toast.makeText() :

 runOnUiThread(new Runnable() { public void run() { Toast toast = Toast.makeText(getApplicationContext(), "Something", Toast.LENGTH_SHORT).show(); } }); 

Le code ci-dessus garantit que vous affichez le message Toast dans un UI thread puisque vous l’appelez à l’intérieur de la méthode runOnUiThread . Donc plus de java.lang.RuntimeException .

Toast.makeText() doit être appelé à partir du thread Main / UI. Looper.getMainLooper() vous aide à y parvenir:

 new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT); } }); 

Un avantage de cette méthode est que vous pouvez également l’utiliser dans des classes non liées à l’activité (ou sans contexte).

J’avais cette erreur jusqu’à ce que je fasse ce qui suit.

 public void somethingHappened(final Context context) { Handler handler = new Handler(Looper.getMainLooper()); handler.post( new Runnable() { @Override public void run() { Toast.makeText(context, "Something happened.", Toast.LENGTH_SHORT).show(); } } ); } 

Et en a fait une classe singleton:

 public enum Toaster { INSTANCE; private final Handler handler = new Handler(Looper.getMainLooper()); public void postMessage(final Ssortingng message) { handler.post( new Runnable() { @Override public void run() { Toast.makeText(ApplicationHolder.INSTANCE.getCustomApplication(), message, Toast.LENGTH_SHORT) .show(); } } ); } } 

C’est ce que j’ai fait.

 new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { Toast(...); } }); 

Les composants visuels sont “verrouillés” aux modifications des threads externes. Donc, comme le toast montre des choses sur l’écran principal qui est géré par le thread principal, vous devez exécuter ce code sur ce thread. J’espère que cela pourra aider:)

C’est parce que Toast.makeText () appelle à partir d’un thread de travail. Ce devrait être l’appel du thread principal de l’interface utilisateur comme ceci

 runOnUiThread(new Runnable() { public void run() { Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT); } }); 

La réponse de ChicoBird a fonctionné pour moi. Le seul changement que j’ai fait a été la création de l’UIHandler où je devais faire

 HandlerThread uiThread = new HandlerThread("UIHandler"); 

Eclipse a refusé d’accepter autre chose. Cela fait sens je suppose.

De plus, le uiHandler est clairement une classe globale définie quelque part. Je ne prétends toujours pas comprendre comment Android fait cela et ce qui se passe, mais je suis content que cela fonctionne. Maintenant, je vais procéder à l’étude et voir si je peux comprendre ce que fait Android et pourquoi il faut passer par tous ces obstacles. Merci pour l’aide ChicoBird.

Pour Rxjava et RxAndroid User:

 public static void shortToast(Ssortingng msg) { Observable.just(msg) .observeOn(AndroidSchedulers.mainThread()) .subscribe(message -> { Toast.makeText(App.getInstance(), message, Toast.LENGTH_SHORT).show(); }); } 

Je rencontrais le même problème lorsque mes rappels essayaient d’afficher une boîte de dialog.

Je l’ai résolu avec des méthodes dédiées dans l’activité – au niveau des membres de l’instance d’ activité – qui utilisent runOnUiThread(..)

 public void showAuthProgressDialog() { runOnUiThread(new Runnable() { @Override public void run() { mAuthProgressDialog = DialogUtil.getVisibleProgressDialog(SignInActivity.this, "Loading ..."); } }); } public void dismissAuthProgressDialog() { runOnUiThread(new Runnable() { @Override public void run() { if (mAuthProgressDialog == null || ! mAuthProgressDialog.isShowing()) { return; } mAuthProgressDialog.dismiss(); } }); } 

Pour afficher une boîte de dialog ou un grid-pain dans un thread, la méthode la plus concise consiste à utiliser l’object Activity.

Par exemple:

 new Thread(new Runnable() { @Override public void run() { myActivity.runOnUiThread(new Runnable() { public void run() { myActivity.this.processingWaitDialog = new ProgressDialog(myActivity.this.getContext()); myActivity.this.processingWaitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); myActivity.this.processingWaitDialog.setMessage("abc"); myActivity.this.processingWaitDialog.setIndeterminate(true); myActivity.this.processingWaitDialog.show(); } }); expenseClassify.serverPost( new AsyncOperationCallback() { public void operationCompleted(Object sender) { myActivity.runOnUiThread(new Runnable() { public void run() { if (myActivity.this.processingWaitDialog != null && myActivity.this.processingWaitDialog.isShowing()) { myActivity.this.processingWaitDialog.dismiss(); myActivity.this.processingWaitDialog = null; } } }); // .runOnUiThread(new Runnable() ... 

Toast, AlertDialogs doit s’exécuter sur le thread de l’interface utilisateur, vous pouvez utiliser Asynctask pour les utiliser correctement dans le développement Android. Mais dans certains cas, nous devons personnaliser les délais, nous utilisons donc Threads , mais nous ne pouvons pas utiliser dans AsyncTask.So nous avons besoin d’un gestionnaire séparé pour les popup.

 public void onSigned() { Thread thread = new Thread(){ @Override public void run() { try{ sleep(3000); Message message = new Message(); message.what = 2; handler.sendMessage(message); } catch (Exception e){ e.printStackTrace(); } } }; thread.start(); } 

Dans l’exemple ci-dessus, je souhaite mettre mon thread en veille dans 3sec et après que je veuille afficher un message Toast, pour cela dans votre gestionnaire d’ implémentation mainthread .

 handler = new Handler() { public void handleMessage(Message msg) { switch(msg.what){ case 1: Toast.makeText(getActivity(),"cool",Toast.LENGTH_SHORT).show(); break; } super.handleMessage(msg); } }; 

J’ai utilisé switch case ici, car si vous avez besoin d’afficher un message différent de la même manière, vous pouvez utiliser switch case dans la classe Handler … j’espère que cela vous aidera

Cela se produit généralement lorsque quelque chose sur le thread principal est appelé depuis n’importe quel thread d’arrière-plan. Regardons un exemple, par exemple.

 private class MyTask extends AsyncTask { @Override protected Void doInBackground(Void... voids) { textView.setText("Any Text"); return null; } } 

Dans l’exemple ci-dessus, nous définissons du texte sur la textview qui se trouve dans le thread d’interface utilisateur principal à partir de la méthode doInBackground (), qui ne fonctionne que sur un thread de travail.

Premier besoin d’importer une ligne donnée.

 import android.os.SsortingctMode; 

Et puis, ajoutez les lignes ci-dessous dans la méthode onCreate() de votre activité:

 SsortingctMode.ThreadPolicy policy = new SsortingctMode.ThreadPolicy.Builder().permitAll().build(); SsortingctMode.setThreadPolicy(policy); 

j’utilise le code suivant pour afficher le message du “contexte” du thread non principal,

 @FunctionalInterface public interface IShowMessage { Context getContext(); default void showMessage(Ssortingng message) { final Thread mThread = new Thread() { @Override public void run() { try { Looper.prepare(); Toast.makeText(getContext(), message, Toast.LENGTH_LONG).show(); Looper.loop(); } catch (Exception error) { error.printStackTrace(); Log.e("IShowMessage", error.getMessage()); } } }; mThread.start(); } } 

puis utiliser comme suit:

 class myClass implements IShowMessage{ showMessage("your message!"); @Override public Context getContext() { return getApplicationContext(); } }