首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android Message 已在使用中崩潰?每次發送必須 new Message 或用 obtainMessage

     編輯:程式設計綜合問答

錯誤堆疊核心訊息

android.util.AndroidRuntimeException: { what=102 ... } This message is already in use.

根因

同一個 `Message` 物件**被重複發送/加入佇列**。`Message` 內部有 `next` 指標用於鏈表佇列,一旦已在佇列中(`in use`),再次 `handler.sendMessage(msg)` 會拋出此異常。

錯誤程式碼模式

// 錯誤:重複使用同一 Message 實例
Message msg = handler.obtainMessage(WHAT, data);
handler.sendMessage(msg);
// ... 稍後又發送同一 msg
handler.sendMessage(msg); // CRASH!

正確做法:每次發送獲取新實例

方式一:Handler.obtainMessage()(推薦,池化復用)

// 發送時現取現用
handler.sendMessage(handler.obtainMessage(WHAT, data));
// 或
Message msg = handler.obtainMessage(WHAT, arg1, arg2, obj);
handler.sendMessage(msg);

方式二:new Message()(簡單但頻繁 GC)

Message msg = new Message();
msg.what = WHAT;
msg.obj = data;
handler.sendMessage(msg);

方式三:Message.obtain() 靜態工廠

Message msg = Message.obtain(handler, WHAT, data);
handler.sendMessage(msg);

代碼修正示例

// 原代碼片段中,發送訊息處應改為:
// case comm_frame.SYS_CFG_RSP_FRM:
//     handler.sendMessage(handler.obtainMessage(comm_frame.SYS_CFG_RSP_FRM, sys_cfg_rsp_info));
//     break;
// case comm_frame.EVENT_RSP_FRM:
//     handler.sendMessage(handler.obtainMessage(comm_frame.EVENT_RSP_FRM, event_info_rsp));
//     break;

最佳實踐總結

  • **永遠不要**持有 `Message` 成員變數並多次發送。
  • 發送點**就地**呼叫 `obtainMessage()` / `new Message()`。
  • 若需延遲發送,用 `handler.sendMessageDelayed(handler.obtainMessage(...), delayMillis)`。
  • 處理 `msg.obj` 時注意型別轉換安全,建議配合 `instanceof` 或泛型封裝。

總結

`This message is already in use` 經典原因是**重複發送同一 Message 實例**。改用 `handler.obtainMessage()` 即時獲取新實例(或從池復用),問題立即解決。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved