| 難點 | 解決方案 |
| 不能阻塞系統 UI 執行緒 | 將所有業務邏輯移至獨立工作執行緒,UI 事件僅負責通知 |
| 工作執行緒如何阻塞等待結果 | Java 經典 wait()/notifyAll() + 信號量標誌 (boolean flag) |
| 跨執行緒傳遞用戶選擇 | 共享 mutable holder (如 int[] result = new int[1]) 或 AtomicInteger |
實現架構圖解
+------------------+ +------------------+ +------------------+
| Worker Thread | | System UI Thread| | Dialog Instance |
| (Business Logic) | | (Event Dispatch) | | (Form + Commands)|
+--------+---------+ +--------+---------+ +--------+---------+
| | |
| 1. new Dialog() | |
|--------------------------->| |
| | 2. display.setCurrent(dlg) |
| |--------------------------->|
| | |
| 3. synchronized(lock) | |
| lock.wait() -----------| (BLOCKED) |
| | |
| | 4. User presses YES/NO |
| |<---------------------------|
| | |
| | 5. commandAction() |
| | result[0] = YES |
| | lock.notifyAll() ------>|
| | |
| 6. lock.wait() returns | |
| read result[0] | |
|<---------------------------| |
| 7. continue logic... | |
核心代碼骨架
public class BlockingDialog {
private final Object lock = new Object();
private final int[] result = new int[1]; // 可變容器傳遞結果
private volatile boolean signaled = false;
public int show(String title, String msg, int type) {
// 必須在非 UI 執行緒呼叫
final Form dialog = new Form(title);
dialog.append(msg);
final Command cmdYes = new Command("是", Command.OK, 1);
final Command cmdNo = new Command("否", Command.CANCEL, 1);
dialog.addCommand(cmdYes);
dialog.addCommand(cmdNo);
// 臨時 CommandListener 僅服務此對話框
dialog.setCommandListener(new CommandListener() {
public void commandAction(Command c, Displayable d) {
synchronized (lock) {
if (c == cmdYes) result[0] = Dialog.YES;
else if (c == cmdNo) result[0] = Dialog.NO;
signaled = true;
lock.notifyAll();
}
}
});
Display.getDisplay(midlet).setCurrent(dialog);
synchronized (lock) {
while (!signaled) {
try { lock.wait(); } catch (InterruptedException ignore) {}
}
}
return result[0];
}
}
使用範例(工作執行緒中)
public class GameLogicThread extends Thread {
private BlockingDialog dialog = new BlockingDialog();
public void run() {
// ... 遊戲邏輯 ...
if (needConfirm) {
int choice = dialog.show("確認", "繼續遊戲?", Dialog.YES_NO);
if (choice == Dialog.YES) continueGame();
else showMainMenu();
}
// ... 後續邏輯線性撰寫 ...
}
}
關鍵注意事項
- 絕不可在 UI 執行緒 (commandAction/paint/keyPressed) 中呼叫 show() → 死鎖
- 對話框顯示期間,系統 UI 執行緒仍正常處理繪製、按鍵、來電等事件
- 適用於「邏輯連貫、分支較少」的同步交互;複雜多層巢狀對話框仍建議狀態機設計
- MIDP 2.0+ 可結合
Alert 簡化實現,但 Alert 無法自定義命令文本/佈局
結語
以「工作執行緒 + wait/notify + 共享結果容器」打破事件回調的邏輯碎片化,實現類 Win32 Dialog 的同步阻塞交互。此模式在 J2ME 遊戲邏輯、嚮導式流程、關鍵確認對話中極具價值,讓受限平台上的代碼保持線性可讀與邏輯內聚。
- 上一篇文章: J2ME 字型與色彩設定完整指南:Font 工廠模式與 RGB/十六進制雙模色彩
- 下一篇文章: J2ME Unit 單元測試框架完整實戰指南:從環境搭建到真機測試
Copyright ©
程式碼之家 All Rights Reserved