內容提要:
在手機這么小的屏幕上開發應用,難點之一就是頻繁的屏幕切換。盡管midp2.0的UI部分已經很豐富了,但這些UI部件都是基于事件回調的。這在處理大量的、簡單的問答式交互時顯得力不從心。
本文實現了一個阻塞當前線程的對話框,簡要地說,你可以使用諸如win32API中dialog函數那樣的方式來實現對話框并阻塞等待返回值,然后根據返回值進行不同的處理。聽起來很誘人吧。
正文:
問題何在?
首先回顧一下midp UI的事件處理機制。有兩個要點:
1)首先UI部分由系統的一個線程負責維護。也就是說不能阻塞系統的事件處理方法。
2)事件處理使用的是一種回調機制。首先UI部件使用諸如setCommandListener之類的方法為自己注冊一個回調接口(其中的回調方法由用戶實現);等到觸發了相應事件就調用這個注冊好的接口的回調方法。
以下是一個實現了CommandListener的類的代碼片斷:
Form f=new Form("Hello world");
f.addCommand(exit);
f.setCommandListener(this);
可以想象基于事件回調的處理方式,在處理大量的、簡單的問答式交互時顯得力不從心。你不得不為每一個僅僅是詢問要不要繼續的對話框而實現一個又一個類,或者處理一個復雜的回調函數。如果選擇后者,那么在一個又一個的if-else中處理不同邏輯事件的代碼片斷一定會煩死你。
較好的做法
這時候我們不免懷念一下win32 Api中對話框函數的處理方式:
int choose=Dialog(title,type……);
if(choose==OK){……}
else if(choose==Cancel){……}
這樣處理將會阻塞當前線程,等待返回值,然后根據返回值進行處理。這樣做很cool的原因就是在一個邏輯性很完整的任務中,你可以一次性在一個回調方法中完成所有邏輯,而不必為了問詢簡單的YES/NO問題而在不同的類中間跳來跳去。
如何在MIDP下實現
我們遇到的第一個問題來自于我們的方法必須要阻塞當前線程等待返回值。也就是說,這個對話框不能在UI的回調中直接運行,比如commandAction中。解決辦法是將所有的事件處理都放到一個線程類中處理。(這是一點額外的負擔,但不可避免)。還好這個工作量不大,要想實現兩個對象之間的通信也不難。
第二個問題是如何阻塞當前的線程,我們祭出java線程的三板斧之wait()/notifyAll()。我們可以指定一個信號量(初值false),當其為false時阻塞當前線程,在得到用戶通知后將信號量改為true,并喚醒線程。
下面看一下主要思路:

看一下代碼:
如何使用
我編寫了一個Test。當用戶按下show按鈕時,開啟對話框,并將用戶的選擇打印出來。
屏幕快照

按下show

用戶多次選擇的結果

(出處:http://www.survivalescaperooms.com)