Не удается создать обработчик внутри потока, который не вызвал Looper.prepare () - PullRequest
879 голосов
/ 06 октября 2010

Что означает следующее исключение; как я могу это исправить?

Это код:

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

Это исключение:

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)

Ответы [ 21 ]

7 голосов
/ 23 декабря 2011

Ответ от ChicoBird работал для меня. Единственное изменение, которое я сделал, было в создании UIHandler, где я должен был сделать

HandlerThread uiThread = new HandlerThread("UIHandler");

Затмение отказалось принять что-либо еще. Имеет смысл, я полагаю.

Кроме того, uiHandler явно является глобальным классом, определенным где-то. Я до сих пор не утверждаю, что понимаю, как Android это делает и что происходит, но я рад, что это работает. Теперь я приступлю к его изучению и выясню, могу ли я понять, что делает Android и почему нужно пройти через все эти обручи и петли. Спасибо за помощь ChicoBird.

6 голосов
/ 05 сентября 2018
 runOnUiThread(new Runnable() {
            public void run() {
                Toast.makeText(mContext, "Message", Toast.LENGTH_SHORT).show();
            }
        });
5 голосов
/ 05 мая 2017

Для пользователей Rxjava и RxAndroid:

public static void shortToast(String msg) {
    Observable.just(msg)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(message -> {
                Toast.makeText(App.getInstance(), message, Toast.LENGTH_SHORT).show();
            });
}
4 голосов
/ 12 января 2017

Я столкнулся с той же проблемой, когда мои обратные вызовы пытались показать диалог.

Я решил это с помощью специальных методов в Activity - на Activity на уровне элемента - которые используют 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();
        }
    });
}
4 голосов
/ 22 марта 2019

Замечательное решение Kotlin:

runOnUiThread {
    // Add your ui thread code here
}
2 голосов
/ 26 февраля 2019
Handler handler2;  
HandlerThread handlerThread=new HandlerThread("second_thread");
handlerThread.start();
handler2=new Handler(handlerThread.getLooper());

Теперь обработчик2 будет использовать другой поток для обработки сообщений, отличный от основного потока.

1 голос
/ 26 августа 2016

Чтобы отобразить диалог или тостер в потоке, наиболее кратким способом является использование объекта Activity.

Например:

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()
...
0 голосов
/ 05 июля 2016

Toast, AlertDialogs необходимо запустить в потоке пользовательского интерфейса, вы можете использовать Asynctask для их правильного использования в разработке Android. Но в некоторых случаях нам нужно настроить время ожидания, поэтому мы используйте Потоки , но в потоках мы не можем использовать Toast, Alertdialogs, как мы используем в AsyncTask. Поэтому нам нужно отдельный Обработчик для всплывающих окон.

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();
}

В приведенном выше примере я хочу перевести свою нить в спящий режим на 3 секунды, и после того, как я хочу показать сообщение Toast, для этого в вашем 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);
       }
};

Я использовал здесь регистр коммутатора, потому что если вам нужно показать разные сообщения таким же образом, вы можете использовать регистр коммутатора в классе Handler ... надеюсь, это поможет вам

0 голосов
/ 09 ноября 2018

У меня была та же проблема, и я исправил ее, просто поместив Toast в функцию переопределения onPostExecute () в Asynctask <>, и она заработала.

0 голосов
/ 20 апреля 2018

Обычно это происходит, когда что-то в основном потоке вызывается из какого-либо фонового потока. Давайте посмотрим на пример, например.

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


@Override
protected Void doInBackground(Void... voids) {
        textView.setText("Any Text");
        return null;
    }
}

В приведенном выше примере мы устанавливаем текст для textview, который находится в основном потоке пользовательского интерфейса, из метода doInBackground (), который работает только в рабочем потоке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...