缩略信息是: sending message to a Handler on a dead thread 我是用IntentService时报的

稍微纤细一点儿的信息是: Handler (android.os.Handler) {215ddea8} sending message to a Handler on a dead thread。

在另一次在IntentService里使用MediaPlayer 播放铃声也再现错误,信息是:Handler) {42414500} sending message to a Handler on a dead thread。

本次的完整信息是:

W/ActivityManager( 1394): getTasks: caller 10034 is using old GET_TASKS but privileged; allowing

W/MessageQueue( 7666): Handler (android.os.Handler) {215ddea8} sending message to a Handler on a dead thread

W/MessageQueue( 7666): java.lang.IllegalStateException: Handler (android.os.Handler) {215ddea8} sending message to a Handler on a dead thread

W/MessageQueue( 7666):  at android.os.MessageQueue.enqueueMessage(MessageQueue.java:325)

W/MessageQueue( 7666):  at android.os.Handler.enqueueMessage(Handler.java:635)

W/MessageQueue( 7666):  at android.os.Handler.sendMessageAtTime(Handler.java:604)

W/MessageQueue( 7666):  at android.os.Handler.sendMessageDelayed(Handler.java:574)

W/MessageQueue( 7666):  at android.os.Handler.postDelayed(Handler.java:398)

W/MessageQueue( 7666):  at com.bandwidthx.library.l.a(SourceFile:367)

W/MessageQueue( 7666):  at com.bandwidthx.library.l.B(SourceFile:357)

W/MessageQueue( 7666):  at com.bandwidthx.library.BxApproval.aZ(SourceFile:4563)

W/MessageQueue( 7666):  at com.bandwidthx.library.BxApproval.aT(SourceFile:4440)

W/MessageQueue( 7666):  at com.bandwidthx.library.BxApproval.aS(SourceFile:4431)

W/MessageQueue( 7666):  at com.bandwidthx.library.BxApproval.aG(SourceFile:4044)

W/MessageQueue( 7666):  at com.bandwidthx.library.l.a(SourceFile:1320)

W/MessageQueue( 7666):  at com.bandwidthx.library.l.j(SourceFile:1275)

W/MessageQueue( 7666):  at com.bandwidthx.library.q.w(SourceFile:2280)

W/MessageQueue( 7666):  at com.bandwidthx.library.q.a(SourceFile:3399)

W/MessageQueue( 7666):  at com.bandwidthx.library.q.a(SourceFile:3103)

W/MessageQueue( 7666):  at com.bandwidthx.library.q$1.a(SourceFile:1959)

W/MessageQueue( 7666):  at com.bandwidthx.library.q$1.doInBackground(SourceFile:1928)

W/MessageQueue( 7666):  at android.os.AsyncTask$2.call(AsyncTask.java:292)
W/MessageQueue( 7666):  at java.util.concurrent.FutureTask.run(FutureTask.java:237)

W/MessageQueue( 7666):  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)

W/MessageQueue( 7666):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)

W/MessageQueue( 7666):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)

W/MessageQueue( 7666):  at java.lang.Thread.run(Thread.java:818)

估计Looper啊,MessageQueue之类的,已经被你们说烂了。

我就简单概括一句(当然下面也有很详细的)

一旦一个线程的消息循环退出后,不能再给其发送消息,否则会有RuntimeException抛出。
就是你一般性看到的:

"RuntimeException: Handler{xxxx} sending message to a Handler on a dead thread"。

一般性的,如果是你实现自己的Looper和Handler,建议在Looper.prepare()后,调用Looper.myLooper()来获取对这个线程Looper的引用。
用途:0. 可以调用quit()终止服务线程   1. 接收消息时检查消息循环是否已经退出

值得一说的是: 线程终止了,有时候并不是你自己终止的,很可能能是系统的某个正常的时序导致的(只是你没有注意到这个次序,然后写代码的时候没有注意)



上面已经说清楚了,下面是详细信息&啰嗦分界线(下面再多说也就这么回事儿,别往下看了,下面就说一个简单的案例)

案例:(使用 IntentService 的发送短信,代码如下)

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

(明眼人一看就知道,那个catch语句写的有问题)

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

结果就报错了:

Google了一下资料,网址上是这么说的:

(大意翻译: 原因是你在一个由intentService控制生命周期的线程种创建了toast,手机先会显示这个toast,之后还是用这个线程的handler去隐藏&关闭这个toast;但是当onHandleIntent结束的时候,这个线程就挂了,然后绑定在这个线程上的handler也就不存在了,完事儿这个toast就关闭不了了,怎么办呢?发给主线程吧,它的toast的Handeler还存活,可以隐藏toast)

解决方案呢?(简单,粗暴)


哪些问题还有什么没有说?

为什么会向一个死线程发消息呢?

因为onHandleIntent(Intent intent)结束了这个线程也就没有了,到底怎么回事儿?

handler没有了,所以cannot hide toast?

如果我没有记错的话,这个toast的生命周期应该是NotificationManagerService控制的吧?

(IntentService源码剖析)----TODO

(Toast生命周期源码剖析)----TODO

时间: 2024-10-01 03:25:52

缩略信息是: sending message to a Handler on a dead thread 我是用IntentService时报的的相关文章

IntentService中使用Toask报错sending message to a Handler on a dead thread

在自己IntentSevice继承类中的onHandleIntent方法中写Toast.makeText(getApplicationContext(), "sd不存在", Toast.LENGTH_SHORT).show();时不会有任何提示,logcat中提示"sending message to a Handler on a dead thread"错误.后从网上差报错原因了解到当一个线程的消息循环已经退出后,不能再给其发送消息不如就会报错.后有从一个网站找到

Android图片与缩略

/** * 将图片文件原比例缩略,并使其不超过最大宽.高 * @param path : 图片文件 * @param requestW : 缩略后最大宽度 * @param requestH : 缩略后最大高度 * @return 缩略后图片对象 */ public static Bitmap getThumbnailByReq(String path,int requestW, int requestH){ BitmapFactory.Options options = new Options

小组项目需求规格说明书【缩略版】

[需求规格说明]详细请见我组需求规格说明书  此处为缩略版 1.引言 1.1编写目的 为明确软件需求.安排项目规划与进度.组织软件开发与测试,撰写本文档. 本文档供项目经理.设计人员.开发人员参考. 项目目标:搭建水果预定网页端平台,并建立相应的数据库,有利于为在校大学生提供一个方便新鲜实惠的水果购买平台. 1.2项目背景 在校大学生对水果的需求量大,但是购买渠道单一,水果价格较高不实惠. "物美价廉"一直是在校大学生所追求的物质享受,而水果价格的普遍大幅度上涨,许多大学生称"

JS显示文献来源和缩略词

<html><head> <title></title> <style type="text/css"> abbr{ text-decoration:underline; } body{ background-color:#ccc; color:#333; font-size: 20px; } </style></head><body> <h1>what is the Docum

IOS如何创建视频缩略图片

//将完整的图片和缩略后的图片写入临时文件夹中     NSData *pngImage = UIImagePNGRepresentation(thumbnail);     if ([pngImage writeToFile:[NSString stringWithFormat:@"%@/tempImage.png",TEMP_FOLDER] atomically:YES]) { UIImage *myThumbNail = [[UIImage alloc] initWithData

css之单行缩略..以及多行缩略

html单行缩略方法 .oneline { white-space: nowrap; //强制文本在一行内输出 overflow: hidden; //隐藏溢出部分 text-overflow: ellipsis; //对溢出部分加上... } html多行缩略(主要针对webkit内核) .multiline { display: -webkit-box !important; overflow: hidden; text-overflow: ellipsis; word-break: bre

显示缩略列表 JS DOM

以下body部分: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Explaining the Ddocument Ob Model</title> <link href="style08.css" type="text/css" rel="sty

cas单点注销失败Error Sending message to url endpoint

最近在做cas单点登录时,由于是单点登录.必然会涉及到单点注销,然而在做单点注销时由于对cas注销机制不了解加之测试条件所致,所有测试都是在本机下完成(机器性能较低,没用虚拟机):导致折腾了很久.网上说的原因也各式各样,大部分原因集中在: 1:你的CAS服务器将cookie设置成了浏览器有效,那么表示如果浏览器不关闭,则一直有效. 在WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml中设置cookie有效期,默

JavaScript编程艺术-第8章-8.6.1-显示“缩略词语表”

8.6.1-显示"缩略词语表" ***代码亲测可用*** HTML: JS: ***end***