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


Que signifie l'exception suivante? comment puis-je le réparer?

C'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.<init>(Handler.java:121)
     at android.widget.Toast.<init>(Toast.java:68)
     at android.widget.Toast.makeText(Toast.java:231)

767
2017-10-06 17:18


origine


Réponses:


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

Chercher Communiquer avec le fil de l'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 un AsyncTask, cela 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 c'est fait.

Vous pouvez également utiliser Activity.runOnUiThread ().


541
2017-10-06 17:20



Vous devez appeler Toast.makeText(...) à partir du fil de l'interface utilisateur:

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

Ceci est copié à partir de une autre réponse (double).


750
2018-03-22 02:11



MISE À JOUR - 2016

La meilleure alternative est d'utiliser RxAndroid (liaisons spécifiques pour RxJava) pour le P dans MVP prendre en charge les données.

Commencez par revenir Observable de votre méthode existante.

private Observable<PojoObject> getObservableItems() {
    return Observable.create(subscriber -> {

        for (PojoObject pojoObject: pojoObjects) {
            subscriber.onNext(pojoObject);
        }
        subscriber.onCompleted();
    });
}

Utilisez cet Observable comme ceci -

getObservableItems().
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribe(new Observer<PojoObject> () {
    @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 threads à savoir Fil de l'interface utilisateur et fil de fond. Selon la documentation android -

N'accédez pas à la boîte à outils de l'interface utilisateur Android en dehors du thread d'interface utilisateur pour résoudre ce problème, Android propose plusieurs façons d'accéder au thread d'interface utilisateur à partir d'autres threads. Voici une liste de méthodes qui peuvent 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 font   ne pas avoir de boucle de message associée à eux; pour en créer un, appelez   prepare () dans le thread qui doit exécuter la boucle, puis loop () pour   avoir des messages de traitement 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 utilisateur   interface. Il effectue les opérations de blocage dans un thread de travail et   puis publie les résultats sur le fil de l'interface utilisateur, sans vous obliger à   manipulez les fils et / ou les manipulateurs vous-même.

public void onClick(View v) {
    new CustomTask().execute((Void[])null);
}


private class CustomTask extends AsyncTask<Void, Void, Void> {

    protected Void doInBackground(Void... param) {
        //Do some work
        return null;
    }

    protected void onPostExecute(Void param) {
        //Print Toast or open dialog
    }
}

Gestionnaire

Un gestionnaire vous permet d'envoyer et de traiter des objets Message et Runnable   associé à 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;
    }
});

412
2018-06-02 19:32



Essayez ceci, quand vous voyez runtimeException en raison de Looper pas préparé avant le gestionnaire.

Handler handler = new Handler(Looper.getMainLooper()); 

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

65
2018-06-13 07:26



J'ai rencontré le même problème, et voici comment je l'ai réparé:

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, (String)msg.obj, Toast.LENGTH_LONG);
            t.show();
        }
        case UIHandler.DISPLAY_UI_DIALOG:
            //TBD
        default:
            break;
        }
    }
}

protected void handleUIRequest(String message)
{
    Message msg = uiHandler.obtainMessage(UIHandler.DISPLAY_UI_TOAST);
    msg.obj = message;
    uiHandler.sendMessage(msg);
}

Pour créer 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.


39
2017-11-30 19:35



Raison d'une erreur:

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

Donc, si vous êtes dans un activity mais en appelant Toast.makeText() à partir du thread de travail, faites ceci:

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 runOnUiThread méthode. Donc pas plus java.lang.RuntimeException.


32
2018-05-16 07:40



Toast.makeText() doit être appelé à partir du thread principal / interface utilisateur. 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 sans activité (ou sans contexte).


25
2018-01-24 00:27



Je recevais cette erreur jusqu'à ce que j'ai fait 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 fait cela dans une classe singleton:

public enum Toaster {
    INSTANCE;

    private final Handler handler = new Handler(Looper.getMainLooper());

    public void postMessage(final String message) {
        handler.post(
            new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(ApplicationHolder.INSTANCE.getCustomApplication(), message, Toast.LENGTH_SHORT)
                        .show();
                }
            }
        );
    }

}

21
2017-11-20 13:09