Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 細節之 AndroidRuntimeException:This message is already in use

android 細節之 AndroidRuntimeException:This message is already in use

編輯:關於Android編程

今天在做項目處理消息隊列的時候,遇到了這樣一個問題,一個異常。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內。把其他的大段相關代碼貼上來的目的是方便自己明白出錯情境。請看官勿怪。

但是我的這種方法是肯定可以解決類似問題。


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved