码迷,mamicode.com
首页 > 移动开发 > 详细

android 细节之 AndroidRuntimeException:This message is already in use

时间:2014-08-15 05:04:37      阅读:282      评论:0      收藏:0      [点我收藏+]

标签:异常   android   runtimeexception   message   handler   

今天在做项目处理消息队列的时候,遇到了这样一个问题,一个异常。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,布布扣,bubuko.com

android 细节之 AndroidRuntimeException:This message is already in use

标签:异常   android   runtimeexception   message   handler   

原文地址:http://blog.csdn.net/yiding_he/article/details/38578327

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!