java.lang.RuntimeException:无法在未调用Looper.prepare()的线程中创build处理程序;

我有一个Android应用程序运行一个线程。 我想要一个Toast消息来显示一条消息。

当我这样做,我得到以下例外:

Logcat跟踪:

FATAL EXCEPTION: Timer-0 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$TN.<init>(Toast.java:322) at android.widget.Toast.<init>(Toast.java:91) at android.widget.Toast.makeText(Toast.java:238) 

是否有将Toast消息从线程推送到用户界面的工作?

我得到这个exception,因为我试图从后台线程做一个Toastpopup。
吐司需要一个活动推到用户界面和线程没有。
所以一个解决方法是给这个线程一个到父Activity和Toast的链接。

把这段代码放在你想发送Toast消息的线程中:

 parent.runOnUiThread(new Runnable() { public void run() { Toast.makeText(parent.getBaseContext(), "Hello", Toast.LENGTH_LONG).show(); } }); 

在创build此线程的后台线程中保留一个指向父Activity的链接。 在你的线程类中使用父variables:

 private static YourActivity parent; 

在创build线程时,通过如下构造函数将父Activity作为parameter passing:

 public YourBackgroundThread(YourActivity parent) { this.parent = parent; } 

现在后台线程可以将Toast消息推送到屏幕上。

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

处理器

Handler允许您发送和处理与线程的MessageQueue关联的Message和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; } }); 

http://developer.android.com/guide/components/processes-and-threads.html

另外,Android UI工具包不是线程安全的。 所以,你不能从一个工作者线程操纵你的UI – 你必须从UI线程对你的用户界面进行所有的操作。 因此,Android的单线程模型只有两条规则:

  1. 不要阻塞UI线程
  2. 不要从UI线程之外访问Android UI工具包

您必须检测工作线程中的闲置并在主线程中显示一个敬酒。

请张贴一些代码,如果你想更详细的答案。

代码发布后:

strings.xml

 <string name="idleness_toast">"You are getting late do it fast"</string> 

YourWorkerThread.java

 Toast.makeText(getApplicationContext(), getString(R.string.idleness_toast), Toast.LENGTH_LONG).show(); 

不要使用AlertDialog,做出select。 AlertDialog和Toast是两个不同的东西。

以下是我一直在做的事情:

  public void displayError(final String errorText) { Runnable doDisplayError = new Runnable() { public void run() { Toast.makeText(getApplicationContext(), errorText, Toast.LENGTH_LONG).show(); } }; messageHandler.post(doDisplayError); } 

这应该允许从任一线程调用该方法。

messageHandler在活动中被声明为..

 Handler messageHandler = new Handler(); 

你可以简单地使用BeginInvokeOnMainThread()。 它在设备主(UI)线程上调用一个Action。

 Device.BeginInvokeOnMainThread(() => { displayToast("text to display"); }); 

这很简单,对我来说是完美的!

编辑:如果您使用C#Xamarin工程