今天在做项目处理消息队列的时候。遇到了这样一个问题。一个异常。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. 重新学习vue基础

    1.创建vue实例 var vm = new Vue({ el: '#example', //选择元素 data: {a:1} //基本数据 }) 2.模板语法 (一)基本语法 <span> ...

  2. firefox dispatchevent的问题

    <!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8&qu ...

  3. hdu 1863 畅通project

    #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm& ...

  4. 怎样在点击li时添加样式,移除兄弟样式

    <style type="text/css"> .add{ color:#ff0} </style> <div> <ul> < ...

  5. Python 操作mongodb 简单实例

    1.建立数据库用户 要读写 mongo数据库,默认没有用户名和密码也可以对数据库进行读写操作,但是从安全的角度,最好给要操作的数据库建立用户名和密码. 打开mongo数据库服务,打开mongo.exe ...

  6. oracle调优 浅析有效的游标管理

    浅析有效的游标管理 [思路分析] 能够把游标理解成共享的运行计划,当sql不被共享时.常规的解决思路有两个方向: 1.调整共享池的尺寸(共享池的库缓存区中共享运行计划): 2.sql书写时尽量重用绑定 ...

  7. 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-人机界面HMI自锁按钮和自复位按钮如何理解(Toggle variable Tap variable)

    我分别创建两个按钮,自锁和自复位,绑定到主程序的两个布尔值上去   自锁按钮是指点击一下为TRUE,再点击一下为FALSE,自复位按钮是指按下的时候为TRUE,松开的时候为FALSE(也可以勾选Tap ...

  8. 怎样改动SharePoint管理中心的语言

    在安装了语言包之后,创建站点集的时候,就能够选择语言了. 可是SharePoint管理中心的语言没有变.这个时候.怎么才干让管理中心也使用新的语言呢? 能够依照下面方法. 首先去https://msd ...

  9. 访问vector元素方法的效率比较(转)

    LInux下: gcc 4.47,red hat6 #include<iostream> #include<vector> #include<time.h> usi ...

  10. Srping AOP xml方式

      使用aop需要: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="ht ...