博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
缩略信息是: sending message to a Handler on a dead thread 我是用IntentService时报的
阅读量:6432 次
发布时间:2019-06-23

本文共 5579 字,大约阅读时间需要 18 分钟。

稍微纤细一点儿的信息是: 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; allowingW/MessageQueue( 7666): Handler (android.os.Handler) {215ddea8} sending message to a Handler on a dead threadW/MessageQueue( 7666): java.lang.IllegalStateException: Handler (android.os.Handler) {215ddea8} sending message to a Handler on a dead threadW/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内部实际是开启的一个工作线程。

@Overrideprotected 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

 

转载于:https://www.cnblogs.com/longhs/p/5557711.html

你可能感兴趣的文章
使用 Docker Compose 管理多个容器实例
查看>>
ThinkPHP 删除数据记录 delete 方法
查看>>
Gradle学习笔记(二)--创建Java项目
查看>>
IntelliJ IDEA 快捷键
查看>>
qury-easyui DataGrid 整合struts2增删查该入门实例(三)
查看>>
if a point is inside a square with mathematics
查看>>
Ubuntu(Linux)使用Eclipse搭建C/C++编译环境
查看>>
skyline无插件web的数据加载解析
查看>>
python基础学习第一天
查看>>
硬盘存储双寡头之争 希捷重注中国市场或赢大丰收
查看>>
淘宝电影联合华谊的数据报告,还有哪些重要信息?
查看>>
编译安装PHP
查看>>
css position:static 的使用
查看>>
nfs永久挂载与临时挂载
查看>>
linux查看网络链接状况命令之-netstat
查看>>
我的友情链接
查看>>
UIView的layoutSubviews和drawRect方法何时调用
查看>>
mysql主从同步
查看>>
制作最简化的Linux系统
查看>>
我的友情链接
查看>>