今天在做项目处理消息队列的时候。遇到了这样一个问题。一个异常。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的更多相关文章

  1. 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 ...

  2. Android源码分析之Message

    准备开始写点东西,算是对自己阅读源码的一个记录/笔记,也希望能对同样感兴趣的人有所帮助,希望能坚持下去,加油. 在Android的开发中,我们经常用到Handler.postXXX方法,或者View. ...

  3. Android消息处理机制(Handler 与Message)---01

    一.handler的使用场景为么会有handler?(部分内容图片摘自http://www.runoob.com/w3cnote/android-tutorial-handler-message.ht ...

  4. Android Handler 机制 - Looper,Message,MessageQueue

    Android Studio 2.3 API 25 从源码角度分析Handler机制.有利于使用Handler和分析Handler的相关问题. Handler 简介 一个Handler允许发送和处理M ...

  5. Android Hander、Looper、Message三者之间的联系

    1.首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象:因为Looper.prepare()在一个线程中只能调用一次,所以Mess ...

  6. Android中的Handler,Looper,Message机制

    Android的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了,我们不会直接与MQ打交道,因 ...

  7. Android Bundle、Handler和Message类介绍

    Bundle是一个载体,可以存放基本数据类型.对象等内容,相当于一辆汽车,可以装载很多东西,然后运到需要的地方,例如: Bundle mBundle=new Bundle(); mBundle.put ...

  8. android 细节之 旋转动画

    Flip Animation for Android: 近期项目中用到了一个小动画,让物体实现一定的3D旋转效果,现记录例如以下: public class FlipAnimation extends ...

  9. android 细节之 menu 之 invalidateOptionsMenu

    menu 在 android中是个很经常使用的控件,曾经自己做项目的时候通常都是将系统的menu相关方法在activity中直接删去.而且将主题换为fullscreen,然后再在layout中引入自己 ...

随机推荐

  1. Linq中比较日期大小(部分比较)

    问题:Linq中比较两个时间的年月日部分 表中某个字段的时间和系统时间比较大小(只比较年月日) 思路一:转换成字符串比较 var queryable = dbContext.Table .Where( ...

  2. 按照vue文档使用JavaScript钩子但是却不能执行动画?

    大家刚入VUE肯定是先去阅读文档, 在 进入/离开 & 列表过渡 这一章节有一小节 ---------  JavaScript钩子 详情见vue文档:  https://cn.vuejs.or ...

  3. 【玩转cocos2d-x之三十九】Cocos2d-x 3.0截屏功能集成

    3.0的截屏和2.x的截屏基本上同样.都是利用RenderTexture来处理,在渲染之前调用call函数,然后调用Cocos的场景visit函数对其进行渲染,渲染结束后调用end函数就可以.仅仅是3 ...

  4. centos7,py2和py3共存

    1.查看是否已经安装Python CentOS 7.2 默认安装了python2.7.5 因为一些命令要用它比如yum 它使用的是python2.7.5. 使用 python -V 命令查看一下是否安 ...

  5. 重新 java 对象的 equals 和 hashCode 方法的建议和示例代码

    equals 方法 equals 方法需要满足的规范: 自反性: 对于任意非空引用 x, x.equals(x) 应该返回 true; 对称性: 对于任意引用, 当且仅当 x.equals(y) == ...

  6. zoj How Many Sets I(组合计数)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do? problemId=4535 一个集合s有n个元素,求满足这种集合序列{s1,s2....sk}使S ...

  7. 为 jquery validate 添加验证失败回调

    转载自:https://blog.csdn.net/huang100qi/article/details/52619227 1. jquery Validation Plugin - v1.15.1 ...

  8. paho-mqtt 学习笔记

    Installation The latest stable version is available in the Python Package Index (PyPi) and can be in ...

  9. 采用CDN加速后,如何在程序里获取用户IP地址

    现在很多网站用了CDN技术,但采用CDN技术后,原来用来获取访问源的IP地址的程序已不能正常使用,它拿到的并不是访问源的真实IP地址,而是CDN节点的IP地址,解决方法是对获取IP的代码作一点小改动. ...

  10. NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件

    通道(Channel) 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Channe ...