android 细节之 AndroidRuntimeException:This message is already in use
今天在做项目处理消息队列的时候。遇到了这样一个问题。一个异常。AndroidRuntimeException:This message is already in use。
我当时的详细业务需求情境为。想要跟硬件联动的时候。保持在一定时间内仅仅有一个操作。假设不idle。就又一次发送消息,而且此消息应该delay一段时间,就是TIMEDELAY。
详细出现错误的代码例如以下:
private class ChargecaseServiceHandler extends Handler {
public ChargecaseServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Command command = new Command();
command.command = msg.what;
if (msg.obj != null) {
command.data = (Bundle) msg.obj;
}
if (sIsLoopBleServiceReady) {
if (isIdle) {
switch (msg.what) {
case MESSAGE_KILL:
stopSelf();
break;
case MESSAGE_START_BLE_SCAN:
startBLEScan();
break;
case MESSAGE_CONNECT:
connect(command.data);
break;
case MESSAGE_DISCONNECT:
attemptDisconnect();
break;
case MESSAGE_RELEASE_DEVICE_ID:
clearData();
break;
case MESSAGE_INITIALIZE:
initialize();
break;
case MESSAGE_RESET_BLE:
resetBleController();
break;
case MESSAGE_STARTUP:
startup();
break;
case MESSAGE_REGISTER:
register(command.data);
break;
case MESSAGE_UNREGISTER:
unregister(command.data);
break;
case MESSAGE_RECONNECT:
reconnect();
break;
case MESSAGE_ADDCARD:
addCard(command.data);
break;
case MESSAGE_GETCARDLIST:
getCardList(command.data);
// removeMessages(MESSAGE_GETCARDLIST);
break;
case MESSAGE_GETCARDDETAIL:
getCardDetail(command.data);
break;
case MESSAGE_REMOVECARD:
removeCard(command.data);
break;
case MESSAGE_CHECK_BATTERY:
checkBattery();
break;
case MESSAGE_SET_DEFAULT_CARD:
setDefaultCard(command.data);
break;
case MESSAGE_ZAP_CARD:
zapCard(command.data);
break;
case MESSAGE_SET_LOCK_TIME:
setLockTimer(command.data);
}
} else {
sServiceHandler.sendMessageDelayed(msg, TIMEDELAY);
}
} else {
Toast.makeText(getApplicationContext(),
"Starting ble for you.", Toast.LENGTH_SHORT).show();
}
}
}
然后上网搜了一下。发现实际上说明发送的消息正在消息队列中。表示如今正在被使用。
參考大神的博客后。(大神博客请移步http://blog.csdn.net/aa4790139/article/details/6579009)
发现解决方法:解决的方法又一次创建一个新的消息。发送过去就ok啦!问题解决。
于是我就准备new 一个 message或是obtain 一个message。而不是直接send这个message来进行delay。但是依旧出错,二次出错的代码例如以下:
private class ChargecaseServiceHandler extends Handler {
public ChargecaseServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Command command = new Command();
command.command = msg.what;
if (msg.obj != null) {
command.data = (Bundle) msg.obj;
}
if (sIsLoopBleServiceReady) {
if (isIdle) {
switch (msg.what) {
case MESSAGE_KILL:
stopSelf();
break;
case MESSAGE_START_BLE_SCAN:
startBLEScan();
break;
case MESSAGE_CONNECT:
connect(command.data);
break;
case MESSAGE_DISCONNECT:
attemptDisconnect();
break;
case MESSAGE_RELEASE_DEVICE_ID:
clearData();
break;
case MESSAGE_INITIALIZE:
initialize();
break;
case MESSAGE_RESET_BLE:
resetBleController();
break;
case MESSAGE_STARTUP:
startup();
break;
case MESSAGE_REGISTER:
register(command.data);
break;
case MESSAGE_UNREGISTER:
unregister(command.data);
break;
case MESSAGE_RECONNECT:
reconnect();
break;
case MESSAGE_ADDCARD:
addCard(command.data);
break;
case MESSAGE_GETCARDLIST:
getCardList(command.data);
// removeMessages(MESSAGE_GETCARDLIST);
break;
case MESSAGE_GETCARDDETAIL:
getCardDetail(command.data);
break;
case MESSAGE_REMOVECARD:
removeCard(command.data);
break;
case MESSAGE_CHECK_BATTERY:
checkBattery();
break;
case MESSAGE_SET_DEFAULT_CARD:
setDefaultCard(command.data);
break;
case MESSAGE_ZAP_CARD:
zapCard(command.data);
break;
case MESSAGE_SET_LOCK_TIME:
setLockTimer(command.data);
}
} else {
Message newMsg = sServiceHandler.obtainMessage();
newMsg = msg。
removeMessages(msg.what);
LogHelper.i(LogHelper.CHARGECASE_TAG, newMsg.what + "");
sServiceHandler.sendMessageDelayed(newMsg, TIMEDELAY);
}
} else {
Toast.makeText(getApplicationContext(),
"Starting ble for you.", Toast.LENGTH_SHORT).show();
}
}
}
于是我就产生了思考,这样我得newMsg究竟是不是一个新的message呢?
肯定不是的,不然就没异常了。于是改变写法,让newMsg的what和obj等于原来msg的what和obj,这样做来保持通过handler传递的动作的一致性。和newMsg的崭新性。
果然,不再报异常了。
解决方法例如以下:
private class ChargecaseServiceHandler extends Handler {
public ChargecaseServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Command command = new Command();
command.command = msg.what;
if (msg.obj != null) {
command.data = (Bundle) msg.obj;
}
if (sIsLoopBleServiceReady) {
if (isIdle) {
switch (msg.what) {
case MESSAGE_KILL:
stopSelf();
break;
case MESSAGE_START_BLE_SCAN:
startBLEScan();
break;
case MESSAGE_CONNECT:
connect(command.data);
break;
case MESSAGE_DISCONNECT:
attemptDisconnect();
break;
case MESSAGE_RELEASE_DEVICE_ID:
clearData();
break;
case MESSAGE_INITIALIZE:
initialize();
break;
case MESSAGE_RESET_BLE:
resetBleController();
break;
case MESSAGE_STARTUP:
startup();
break;
case MESSAGE_REGISTER:
register(command.data);
break;
case MESSAGE_UNREGISTER:
unregister(command.data);
break;
case MESSAGE_RECONNECT:
reconnect();
break;
case MESSAGE_ADDCARD:
addCard(command.data);
break;
case MESSAGE_GETCARDLIST:
getCardList(command.data);
// removeMessages(MESSAGE_GETCARDLIST);
break;
case MESSAGE_GETCARDDETAIL:
getCardDetail(command.data);
break;
case MESSAGE_REMOVECARD:
removeCard(command.data);
break;
case MESSAGE_CHECK_BATTERY:
checkBattery();
break;
case MESSAGE_SET_DEFAULT_CARD:
setDefaultCard(command.data);
break;
case MESSAGE_ZAP_CARD:
zapCard(command.data);
break;
case MESSAGE_SET_LOCK_TIME:
setLockTimer(command.data);
}
} else {
Message newMsg = sServiceHandler.obtainMessage();
newMsg.what = msg.what;
newMsg.obj = msg.obj;
removeMessages(msg.what);
LogHelper.i(LogHelper.CHARGECASE_TAG, newMsg.what + "");
sServiceHandler.sendMessageDelayed(newMsg, TIMEDELAY);
}
} else {
Toast.makeText(getApplicationContext(),
"Starting ble for you.", Toast.LENGTH_SHORT).show();
}
}
}
switch的消息非常多。是业务须要,出现的异常也非常经典。特记录之。
PS:网上非常多解决方法是把new Message()换成obtainMessage(),有的说是把obtainMessage()换成new Message(). 个人亲測无法解决,或是无法解决我的问题。
PS2: 出现故障和解决这个问题的地方就是在倒数第二个else内。把其它的大段相关代码贴上来的目的是方便自己明确出错情境。请看官勿怪。
可是我的这样的方法是肯定能够解决类似问题。
android 细节之 AndroidRuntimeException:This message is already in use的更多相关文章
- W/MessageQueue: Handler (android.os.Handler) {4241f8f8} sending message to a Handler on a dead thread
缩略信息是: sending message to a Handler on a dead thread 我是用IntentService时报的 稍微纤细一点儿的信息是: Handler (andro ...
- Android源码分析之Message
准备开始写点东西,算是对自己阅读源码的一个记录/笔记,也希望能对同样感兴趣的人有所帮助,希望能坚持下去,加油. 在Android的开发中,我们经常用到Handler.postXXX方法,或者View. ...
- Android消息处理机制(Handler 与Message)---01
一.handler的使用场景为么会有handler?(部分内容图片摘自http://www.runoob.com/w3cnote/android-tutorial-handler-message.ht ...
- Android Handler 机制 - Looper,Message,MessageQueue
Android Studio 2.3 API 25 从源码角度分析Handler机制.有利于使用Handler和分析Handler的相关问题. Handler 简介 一个Handler允许发送和处理M ...
- Android Hander、Looper、Message三者之间的联系
1.首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象:因为Looper.prepare()在一个线程中只能调用一次,所以Mess ...
- Android中的Handler,Looper,Message机制
Android的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了,我们不会直接与MQ打交道,因 ...
- Android Bundle、Handler和Message类介绍
Bundle是一个载体,可以存放基本数据类型.对象等内容,相当于一辆汽车,可以装载很多东西,然后运到需要的地方,例如: Bundle mBundle=new Bundle(); mBundle.put ...
- android 细节之 旋转动画
Flip Animation for Android: 近期项目中用到了一个小动画,让物体实现一定的3D旋转效果,现记录例如以下: public class FlipAnimation extends ...
- android 细节之 menu 之 invalidateOptionsMenu
menu 在 android中是个很经常使用的控件,曾经自己做项目的时候通常都是将系统的menu相关方法在activity中直接删去.而且将主题换为fullscreen,然后再在layout中引入自己 ...
随机推荐
- 一良心操盘手:我们是这样玩死散户的! z
做庄必须考虑很多问题: 第一是证监会的监控.操控股票不能让他们抓住把柄,这时候就要考虑多户头,或者拉几个私募大户集体作战. 第二要考虑产业资本的问题.如果我们拉的时候,他们看到利润可观,结果大量抛出筹 ...
- java.sql.SQLException: Io 异常: Got minus one from a read call
博客分类: Oracle Tomcat服务器下的应用连接Oracle时报错,出现以下异常: java.sql.SQLException: Io 异常: Got minus one from a r ...
- VR开发者必看:4大最为值得关注的内容平台【转】
时间 2016-01-19 14:12:57 原文 http://www.sfw.cn/xinwen/478369.html 主题 虚拟现实 Oculus 对很多有意涉及VR行业的内 ...
- apache poi合并单元格设置边框
HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet(); //创建一个样式 HSSFCellStyle sty ...
- 深度增强学习--Policy Gradient
前面都是value based的方法,现在看一种直接预测动作的方法 Policy Based Policy Gradient 一个介绍 karpathy的博客 一个推导 下面的例子实现的REINFOR ...
- [Linux]屏幕输出控制
专门的术语叫做ANSI Escape sequences(ANSI Escape codes),题目并不恰当,与其说是屏幕输出控制,不如说是通过bash在兼容VT100的终端上进行输出. 主要有以下类 ...
- [Node.js] Show More Lines in a Node.js Error Stack Trace
Sometimes you are one or two lines short from finding the cause of the error in the stack trace but ...
- 【Android】The application has stopped unexpectedly.Please try again.
打出的android APK在android4.0.2手机上运行正常,但是在2.3.7的MOTO DEFY ME525上运行失败. android 2.3.3版本的模拟器上面运行失败: Sorry! ...
- SkipList的实现
当做笔记记录下来:) 相比于bTree,skiplist占用更多的空间. 而在并发的环境下skiplist会比bTree效率更高. (bTree插入的时候需要rebalance,需要lock比较多的结 ...
- apktool反编译工具使用详解
文章转自: http://zhangyan1158.blog.51cto.com/2487362/683234 一.APKTOOL使用环境配置 1.安装JAVA并设置环境变量. 下载安装都很简单,关键 ...