Невозможно создать обработчик внутри потока, который не вызвал Looper.prepare ()

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

Это код:

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) 

Вы называете это из рабочего потока. Вам нужно вызвать Toast.makeText() (и большинство других функций, связанных с пользовательским интерфейсом) из основного потока. Например, вы можете использовать обработчик.

Посмотрите Связь с линией пользовательского интерфейса в документации. В двух словах:

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

Другие варианты:

Вы можете использовать AsyncTask , который хорошо работает для большинства вещей, работающих в фоновом режиме. У этого есть крючки, которые вы можете вызвать, чтобы указать прогресс, и когда это будет сделано.

Вы также можете использовать Activity.runOnUiThread () .

Вам нужно вызвать Toast.makeText(...) из потока пользовательского интерфейса:

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

Это скопировано из другого (дублированного) ответа SO .

ОБНОВЛЕНИЕ – 2016

Лучшей альтернативой является использование RxAndroid (конкретные привязки для RxJava ) для P в MVP для сбора данных.

Начните с возврата Observable из вашего существующего метода.

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

Используйте это Наблюдаемое как это –

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

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

Я знаю, что немного опаздываю, но здесь. Android в основном работает с двумя типами потоков, а именно с потоком пользовательского интерфейса и фоновым потоком . Согласно документации android –

Не обращайтесь к инструментарию Android UI из-за пределов пользовательского интерфейса, чтобы исправить эту проблему, Android предлагает несколько способов доступа к потоку пользовательского интерфейса из других потоков. Вот список методов, которые могут помочь:

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

Теперь для решения этой проблемы существуют различные методы.

Я объясню это по образцу кода:

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

Класс, используемый для запуска цикла сообщений для потока. Потоки по умолчанию не имеют связанного с ними цикла сообщений; Чтобы создать один, вызовите prepare () в потоке, который должен запустить цикл, а затем loop (), чтобы обработать сообщения до тех пор, пока цикл не будет остановлен.

 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 позволяет выполнять асинхронную работу с вашим пользовательским интерфейсом. Он выполняет операции блокировки в рабочем потоке, а затем публикует результаты в потоке пользовательского интерфейса, не требуя, чтобы вы сами обрабатывали потоки и / или обработчики.

 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 } } 

укротитель

Обработчик позволяет отправлять и обрабатывать объекты Message и Runnable, связанные с MessageQueue потока.

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

Попробуйте это, когда вы увидите исключение runtimeException из-за того, что Looper не подготовлен перед обработчиком.

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

Я столкнулся с той же проблемой, и вот как я ее исправил:

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

Чтобы создать UIHandler, вам необходимо выполнить следующие действия:

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

Надеюсь это поможет.

Причина ошибки:

Рабочие потоки предназначены для выполнения фоновых задач, и вы не можете ничего показывать в пользовательском интерфейсе в рабочем потоке, если вы не вызываете метод, например runOnUiThread . Если вы попытаетесь показать что-либо в потоке пользовательского интерфейса без вызова runOnUiThread, будет исключение java.lang.RuntimeException .

Итак, если вы работаете, но вызываете Toast.makeText() из рабочего потока, сделайте следующее:

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

Вышеприведенный код гарантирует, что вы показываете сообщение Toast в UI thread так как вы вызываете его внутри метода runOnUiThread . Так что не больше java.lang.RuntimeException .

Я получал эту ошибку, пока не сделал следующее.

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

И сделал это в одноэлементном классе:

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

Вот что я сделал.

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

Визуальные компоненты «заблокированы» для изменений из внешних потоков. Итак, поскольку тост показывает материал на главном экране, который управляется основным потоком, вам нужно запустить этот код в этом потоке. Надеюсь, это поможет:)

Преимущество этого метода заключается в том, что вы также можете использовать в неактивных классах:

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

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

 HandlerThread uiThread = new HandlerThread("UIHandler"); 

Eclipse отказался принять что-нибудь еще. Полагаю, я полагаю.

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

Это потому, что Toast.makeText () вызывает из рабочего потока. Он должен быть вызван из основного потока пользовательского интерфейса, как это

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

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

Я решил это с помощью выделенных методов в 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(); } }); } 

Для пользователей 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(); }); } 

Toast, AlertDialogs нужно запускать в потоке пользовательского интерфейса, вы можете использовать Asynctask для правильного использования их в android development.but в некоторых случаях нам нужно настроить тайм-ауты, поэтому мы используем Threads , но в потоках мы не можем использовать Toast, Alertdialogs, как мы используем В AsyncTask.So нам нужен отдельный обработчик для всплывающих окон.

 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 … надеюсь, что это поможет вам

Чтобы отобразить диалог или тостер в потоке, наиболее кратким способом является использование объекта 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() ... 
Intereting Posts
Сохранение данных из списка с помощью SharedPreferences То, что находится на предупреждении о незаконном преследовании в андроиде Потребление отмененных покупок в Google Play In-App Billing Не удалось идентифицировать контакты WhatsApp Как добавить панель действий из библиотеки поддержки в PreferenceActivity? Android: наложение на окно над действиями задачи При сравнении двух равных целых чисел в цикле while оператор с равным оператором терпит неудачу? Android – Присоедините запрос с помощью Content Provider Завершение вкладки в оболочке adb Как сохранить структуру папок при застегивании на Java? Четко очистить мои собственные данные приложений Воспроизведение аудиофайлов в Android-журналах Странная ошибка Стратегия обновления Android-приложения (с базой данных) Приложение Google IO Sched – планшет и фрагменты планшета Как вы масштабируете и набиваете растровое растение, используемое в качестве фона?