不能在没有调用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是使用RxAndroid ( RxAndroid特定绑定)为MVP的P来负责数据。 
 首先从你现有的方法返回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类中使用开关盒…希望这会帮助你