不能在没有调用Looper.prepare()的线程中创build处理程序

以下例外是什么意思; 我该如何解决?

这是代码:

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() (和其他大多数处理UI的函数)。 例如,您可以使用处理程序。

在文档中查找与UI线程进行通信 。 简而言之:

 // 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() 。

您需要从UI线程调用Toast.makeText(...)

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

这是从另一个(重复)SO答复复制粘贴。

更新 – 2016年

最好的select是使用RxAndroidRxAndroid特定绑定)为MVPP来负责数据。

首先从你现有的方法返回Observable

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

像这样使用这个Observable –

 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基本上工作在两个线程types,即UI线程后台线程 。 根据android文档 –

不要从UI线程外部访问Android UI工具包来解决这个问题,Android提供了几种方法从其他线程访问UI线程。 这里是可以帮助的方法列表:

 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

用于为线程运行消息循环的类。 线程默认情况下没有与它们相关的消息循环; 创build一个,在要运行循环的线程中调用prepare(),然后循环()使其处理消息,直到循环停止。

 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允许您在用户界面上执行asynchronous工作。 它在工作线程中执行阻塞操作,然后将结果发布到UI线程上,而无需自己处理线程和/或处理程序。

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

处理器

处理程序允许您发送和处理与线程的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; } }); 

尝试这一点,当你看到由于Looper没有准备好处理程序之前,runtimeException。

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

要创buildUIHandler,您需要执行以下操作:

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

希望这可以帮助。

错误原因:

工作线程用于执行后台任务,除非调用像runOnUiThread这样的方法,否则不能在工作线程的UI上显示任何东西。 如果您尝试在不调用runOnUiThread的情况下在UI线程上显示任何内容,将会出现java.lang.RuntimeException

所以,如果你在一个activity但从工作线程调用Toast.makeText() ,请执行以下操作:

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

上面的代码确保您在UI thread中显示Toast消息,因为您正在使用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(...); } }); 

可视化组件被“locking”来自外部线程的变化。 所以,由于吐司在由主线程pipe理的主屏幕上显示了东西,所以你需要在该线程上运行这个代码。 希望帮助:)

这种方法的一个优点是,你也可以在非活动类中使用:

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

奇科鸟的答案为我工作。 我做的唯一的改变是在UIHandler的创build,我必须做的

 HandlerThread uiThread = new HandlerThread("UIHandler"); 

Eclipse拒绝接受别的东西。 我想是有道理的。

uiHandler显然也是一个全球定义的类。 我还没有声称了解Android是如何做到这一点,发生了什么,但我很高兴它的工作原理。 现在我将着手研究它,看看我能不能理解Android正在做什么,为什么要经历所有这些循环。 感谢ChicoBird的帮助。

这是因为Toast.makeText()正在从工作线程调用。 它应该是这样的主UI线程调用

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

当我的callback尝试显示一个对话框时,我遇到了同样的问题。

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

要在线程中显示对话框或烤面包机,最简洁的方法是使用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() ... 

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

敬酒,AlertDialogs需要在UI线程上运行,你可以使用Asynctask在android开发中正确使用它们。但是有些情况下我们需要定制超时,所以我们使用线程 ,但是在线程中我们不能使用Toast,Alertdialogs就像我们使用在AsyncTask.So我们需要单独的处理程序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(); } 

在上面的例子中,我想在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类中使用开关盒…希望这会帮助你