toast - 无法创建没有调用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() ( 和大多数处理用户界面的函数) 。 你可以使用处理程序,例如。

你需要从用户界面线程调用 Toast.makeText(...):


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

这是copy-pasted来自的另一个( 重复) 所以回答

我知道我有点晚了。 安卓基本上每次对两个线程类型即 UI线程和后台线程 。 根据安卓的文档

不要从用户界面线程访问Android用户界面工具箱来修复这个问题,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();

活套

用于为线程运行消息循环的类。 默认情况下,线程没有与之关联的消息循环;要创建一个,请在运行循环的线程中调用 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
 }
}

处理程序

处理程序允许你发送和处理与线程的MessageQueue关联的消息和Runnable对象。


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

我遇到了同样的问题,下面是我修复它的方法:


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

希望这有帮助

尝试这里选项时,当你在处理程序之前没有准备好 Looper 。


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

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

错误的原因:

工作线程是用来做后台任务的,你不能在工作线程中显示任何东西,除非你的方法像 runOnUiThread 。 如果你试图在不调用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();
 }
 }
 );
 }

}

ChicoBird的答案为我工作。 我做的唯一改变是在UIHandler的创建中,我必须做


HandlerThread uiThread = new HandlerThread("UIHandler");

Eclipse 拒绝接受任何其他内容。 我觉得我觉得。

uiHandler 显然是一个类全局定义的。 我仍然不理解Android是如何做的,以及正在进行的事情,但我很高兴它能工作。 现在我将继续研究它,看看我是否能理解Android正在做什么以及为什么要通过所有这些hoops和循环。 感谢你的帮助 ChicoBird 。

...