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

J2ME 阻塞式對話框實現原理:突破事件回調限制的同步交互模式

     編輯:J2ME

痛點:事件回調模式下的交互地獄

MIDP UI 採用事件回調模型:
1. 系統專用執行緒維護 UI(不可阻塞)
2. 元件註冊 CommandListener,事件觸發回調
後果:簡單的「是/否」確認對話框,迫使開發者編寫獨立類或巨大 if-else 鏈處理邏輯分支,代碼碎片化、難維護。

目標:Win32 Dialog 風格的同步阻塞 API


// 期望的調用方式
int choice = Dialog.show("確定刪除?", Dialog.YES_NO);
if (choice == Dialog.YES) { delete(); }
else { cancel(); }
// 當前執行緒阻塞等待用戶選擇,邏輯連貫、線性可讀

核心難點與解決方案

實現架構圖解

+------------------+          +------------------+          +------------------+
|  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 遊戲邏輯、嚮導式流程、關鍵確認對話中極具價值,讓受限平台上的代碼保持線性可讀與邏輯內聚。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
難點解決方案
不能阻塞系統 UI 執行緒將所有業務邏輯移至獨立工作執行緒,UI 事件僅負責通知
工作執行緒如何阻塞等待結果Java 經典 wait()/notifyAll() + 信號量標誌 (boolean flag)
跨執行緒傳遞用戶選擇共享 mutable holder (如 int[] result = new int[1]) 或 AtomicInteger