java.lang.RuntimeException: Handler (android.os.Handler) sending message to a Handler on a dead thread 意思是:运行时错误:处理程序(android.os.Handler)向已死线程上的处理程序发送消息。

61

在我的应用程序中,我正在使用IntentService发送短信。

    @Override
protected void onHandleIntent(Intent intent) {
    Bundle data = intent.getExtras();
    String[] recipients = null;
    String message = getString(R.string.unknown_event);
    String name = getString(R.string.app_name);
    if (data != null && data.containsKey(Constants.Services.RECIPIENTS)) {
        recipients = data.getStringArray(Constants.Services.RECIPIENTS);
        name = data.getString(Constants.Services.NAME);
        message = data.getString(Constants.Services.MESSAGE);
        for (int i = 0; i < recipients.length; i++) {
            if(!StringUtils.isNullOrEmpty(recipients[i])) {
                try {
                    Intent sendIntent = new Intent(this, SMSReceiver.class);
                    sendIntent.setAction(Constants.SMS.SEND_ACTION);
                    PendingIntent sendPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, sendIntent, PendingIntent.FLAG_UPDATE_CURRENT);
                    Intent deliveryIntent = new Intent(this, SMSReceiver.class);
                    deliveryIntent.setAction(Constants.SMS.DELIVERED_ACTION);
                    PendingIntent deliveryPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, deliveryIntent, PendingIntent.FLAG_UPDATE_CURRENT);
                    SmsManager.getDefault().sendTextMessage(recipients[i].trim(), null, "[" + name + "] " + message, sendPendingIntent, deliveryPendingIntent);
                } catch (Exception e) {
                    Log.e(TAG, "sendTextMessage", e);
                    e.printStackTrace();
                    Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
                    MainActivity.instance.writeToLogFile(e.getMessage(), System.currentTimeMillis());                       
                }
            }
        }
    }
}

运行应用程序时,我遇到了以下错误:

W/MessageQueue(7180): Handler (android.os.Handler) {42586468} sending message to a Handler on a dead thread
W/MessageQueue(7180): java.lang.RuntimeException: Handler (android.os.Handler) {42586468} sending message to a Handler on a dead thread
W/MessageQueue(7180):   at android.os.MessageQueue.enqueueMessage(MessageQueue.java:294)
W/MessageQueue(7180):   at android.os.Handler.enqueueMessage(Handler.java:618)
W/MessageQueue(7180):   at android.os.Handler.sendMessageAtTime(Handler.java:587)
W/MessageQueue(7180):   at android.os.Handler.sendMessageDelayed(Handler.java:558)
W/MessageQueue(7180):   at android.os.Handler.post(Handler.java:323)
W/MessageQueue(7180):   at android.widget.Toast$TN.hide(Toast.java:367)
W/MessageQueue(7180):   at android.app.ITransientNotification$Stub.onTransact(ITransientNotification.java:55)
W/MessageQueue(7180):   at android.os.Binder.execTransact(Binder.java:351)
W/MessageQueue(7180):   at dalvik.system.NativeStart.run(Native Method)

我的SMSReceiver位于另一个类中。 我该如何解决这个问题? 谢谢; Eyal。


你在清单文件中添加了这个服务吗? - Gal Ben-Haim
是的。IntentService毕竟是一个真正的服务... - eyal
3个回答

164

这里的问题在于您正在IntentService管理的线程中创建一个Toast。系统将使用与该线程关联的Handler来显示和隐藏Toast

首先,Toast将被正确显示,但是在onHandleIntent方法完成后,当系统尝试隐藏它时,会抛出“在死线程上向处理程序发送消息”的错误,因为创建Toast的线程不再有效,并且Toast将不会消失。

为了避免这种情况,您应该通过向主线程发送消息来显示Toast。以下是一个示例:

    // create a handler to post messages to the main thread
    Handler mHandler = new Handler(getMainLooper());
    mHandler.post(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(getApplicationContext(), "test", Toast.LENGTH_SHORT).show();
        }
    });

@rubenlop88 我还是不明白当我使用一个可运行对象时问题是如何解决的。我的理解是,当 onHandle 被调用时,它会调用 Toast,然后退出,之后 Toast 就会被隐藏?这是正确的顺序吗?但如果是这样的话,那么当我使用可运行对象时,可运行线程在隐藏 Toast 之前也应该自己结束。我在这里漏掉了什么?谢谢。 - Kraken
@Kraken Runnable 用于在应用程序的主线程上创建 Toast。如果不使用 Runnable,则 Toast 将在由 IntentService 管理的线程中创建。如果 IntentService 线程太快地完成,则 Toast 不会被解除显示。 - rubenlop88
1
很好。它能正常工作,但对于我的情况,问题在于Toast根本没有显示出来。 - Amt87

5

IntentService 上显示 Toast。 尝试使用以下代码:

@Override
public void onCreate() {
    super.onCreate();
    mHandler = new Handler();
}

@Override
protected void onHandleIntent(Intent intent) {
    mHandler.post(new Runnable() {            
        @Override
        public void run() {
            Toast.makeText(MyIntentService.this, "Test", Toast.LENGTH_LONG).show();                
        }
    });
}

来源:- https://dev59.com/vHA75IYBdhLWcg3wbojM#5420929

在IT技术中,“ID”一词通常代表“标识符”,它是一个用于唯一标识某个对象的字符串。例如,在Web开发中,HTML元素可以使用“ID”属性来标识其自身。在JavaScript和CSS中,也可以使用“ID”来选择和修改HTML元素。总之,“ID”是IT技术中常用的一个术语。


2

我认为您需要检查一个条件:

mHandler.getLooper().getThread().isAlive()

该应用程序只会警告您有关此错误的信息。当然,这通常不是致命的错误。 但是,如果有许多此处理程序的生成用法,则这些警告将减慢应用程序的速度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接