前言:誰在掌控你的 MIDlet?
每個 MIDlet 的出生、暫停、銷毀,都由設備上的 Application Management Software (AMS) 統一調度。作為開發者,我們不直接控制狀態流轉,而是通過重寫三個核心回調方法、並在適當時機主動通知 AMS,來實現與系統的協作。
一、 三大被動回調:AMS → MIDlet
| 方法 | 觸發時機 | 典型職責 |
startApp() | MIDlet 首次啟動、或從 Paused 恢復 | 初始化資源、顯示主界面 Display.setCurrent() |
pauseApp() | 來電、短信、用戶切換任務等系統搶佔 | 釋放非必需資源(網絡連接、線程、音頻)、暫停遊戲邏輯 |
destroyApp(boolean unconditional) | 用戶退出、AMS 強制終止 | 持久化數據、關閉 RecordStore、停止所有線程、釋放所有資源 |
注意:destroyApp(true) 表示無條件銷毀,必須返回;false 允許拋出 MIDletStateChangeException 請求繼續運行(罕見)。
二、 三大主動通知:MIDlet → AMS
| 方法 | 用途 | 調用後果 |
notifyDestroyed() | 宣告 MIDlet 已結束 | AMS 回收資源,進程終止 |
notifyPaused() | 請求進入 Paused 狀態 | AMS 稍後調用 pauseApp(),MIDlet 不再佔用前台 |
resumeRequest() | 請求從 Paused 恢復為 Active | AMS 評估資源後調用 startApp() |
三、 狀態機圖解
[Not Exist] --AMS create--> [Paused] --startApp()--> [Active]
^ | |
| v |
+---- destroyApp() -- [Destroyed] |
(notifyDestroyed) |
^ |
|---- pauseApp() -- (notifyPaused) |
| |
+---- resumeRequest() -------------+
四、 實戰代碼範本
public class LifeCycleDemo extends MIDlet implements CommandListener {
private Display display;
private Form mainForm;
private StringBuffer log = new StringBuffer(); // 記錄狀態流轉
protected void startApp() {
log.append("→ startApp()\n");
if (mainForm == null) initUI();
display.setCurrent(mainForm);
}
protected void pauseApp() {
log.append("→ pauseApp()\n");
// 釋放佔用資源:停止動畫線程、關閉網絡連接等
}
protected void destroyApp(boolean unconditional) {
log.append("→ destroyApp(" + unconditional + ")\n");
// 保存設置、關閉 RMS、停止所有線程
}
// 用戶點擊「退出」命令
public void commandAction(Command c, Displayable d) {
if (c.getCommandType() == Command.EXIT) {
destroyApp(true);
notifyDestroyed(); // 必須成對調用
}
}
// ... 其餘代碼省略
}
五、 實測陷阱:來電不一定觸發 pauseApp()
規範規定來電時 AMS 應調用 pauseApp(),但實測中部分廠商實現(如早期 Nokia S40)可能直接銷毀 MIDlet 或完全不回調。防禦性編程建議:
- 在
startApp() 中做冪等初始化,允許重複調用。
- 關鍵數據實時持久化(RMS),不依賴
destroyApp() 才保存。
- 避免在
pauseApp() 執行耗時操作,以免阻塞系統處理來電。
六、 多任務協作最佳實踐
- 資源獲取即用即釋:網絡連接、輸入流、RecordStore 用完立即
close()。
- 後台線程必須可中斷:保留
volatile boolean running 標誌,pauseApp() 置 false,run() 循環檢測退出。
- UI 狀態保存:記住當前顯示的
Displayable、滾動位置、輸入框內容,startApp() 恢復。
- 善用
resumeRequest():後台下載完成、推送消息到達時調用,請求回前台提醒用戶。
七、 總結
MIDlet 生命週期管理的核心是「被動回調 + 主動通知」的雙向契約。深理解狀態機、預判廠商差異、編寫健壯的資源釋放邏輯,是打造穩定、良民 J2ME 應用的必修課。
- 上一篇文章: J2ME Web 服務入門指南:JSR 172 規範核心解析與實戰
- 下一篇文章: J2ME 位置服務 (LBS) 開發指南:JSR 179 核心 API 與最佳實踐
Copyright ©
程式碼之家 All Rights Reserved