我正在尝试通过Toast显示一条简单的消息,并且正在获取RunTime Exception“在死线程上向Handler发送消息”。尝试显示Toast消息的类扩展了IntentService。该类(C2DMReceiver)实际上来自C2DM的ChromeToPhone示例。这是方法:
/**
* Called when a cloud message has been received.
*/
@Override
public void onMessage(Context context, Intent intent) {
Log.i(LOG_TAG, "A message notification has occured with the cloud.");
Log.i(LOG_TAG, "Showing toast message of the broadcast...");
Toast toast = Toast.makeText(context, "Some text", Toast.LENGTH_LONG);
toast.show();
Log.i(LOG_TAG, "Sending notification of the broadcast...");
LauncherUtils.generateNotification(this, "this is where the text would go.", "Broadcast", intent);
}
}
我假设因为类扩展了IntentService,所以可以通过这种方式从这里请求一个简单的Toast消息。这不正确吗?
答案 0 :(得分:28)
这是由于Android框架中的AsyncTask中存在错误。 AsyncTask.java具有以下代码:
private static final InternalHandler sHandler = new InternalHandler();
它期望在主线程上初始化它,但是这不能保证,因为它将在导致类运行其静态初始化器的任何线程上初始化。我重现了Handler引用工作线程的问题。
导致这种情况发生的常见模式是使用IntentService类。 C2DM示例代码执行此操作。
一个简单的解决方法是将以下代码添加到应用程序的onCreate方法中:
Class.forName("android.os.AsyncTask");
这将强制在主线程中初始化AsyncTask。我在android bug数据库中提交了一个bug。请参阅http://code.google.com/p/android/issues/detail?id=20915。
答案 1 :(得分:24)
public class NetworkService extends IntentService {
Handler mMainThreadHandler = null;
public NetworkService() {
super(NetworkService.class.getName());
mMainThreadHandler = new Handler();
}
@Override
protected void onHandleIntent(Intent arg) {
System.out.printf("Network service intent handling: %s\n", arg.toString());
mMainThreadHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "BusyBox updated", Toast.LENGTH_LONG).show();
}
});
}
}
答案 2 :(得分:11)
从后台完成主线程中的消息烘焙的另一种方法是使用一个小实用程序方法。诀窍是创建一个附加到主线程looper的处理程序(Looper.getMainLooper())。
public class ToastUtils {
public static void showToastInUiThread(final Context ctx,
final int stringRes) {
Handler mainThread = new Handler(Looper.getMainLooper());
mainThread.post(new Runnable() {
@Override
public void run() {
Toast.makeText(ctx, ctx.getString(stringRes), Toast.LENGTH_SHORT).show();
}
});
}
}
答案 3 :(得分:0)
您必须从主线程显示Toast,否则它将不会显示在屏幕上。处理程序从创建它的线程执行。如果您在intentservice的onCreate中创建处理程序,它应该在您发送消息时按预期工作。
答案 4 :(得分:0)
未在主线程上调用onMessage方法。
所以你需要制作一个新的Handler。
应用此代码:
public class GCMIntentService extends GCMBaseIntentService
{
Handler handler;
public GCMIntentService()
{
handler = new Handler();
}
}
答案 5 :(得分:0)
您可以在ui线程上运行代码,如下所示:
runOnUiThread(new Runnable() {
public void run() {
try {
//YOUR CODE
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
}
});
这应该可以正常工作