背景:
BlackBerry的顯示堆棧(stack):
Screen對象在一個一組有序的Screen顯示棧里得到維護。在棧頂的Screen對象是顯示給用戶的活動Screen。
當應用程序顯示一個Screen時,它將這個Screen壓入到棧頂。當關閉一個Screen,將這個Screen從棧里移出,然后顯示棧里的下一個Screen,如果必要會重繪它。
每個Screen在棧里只出現一次。如果同一個Screen壓入到棧不止一次,VM會拋出一個運行時異常。
當用戶完成和Screen交互,應用程序必須將Screen從棧里移出,以致內存不必再用。
不要在同一時間里使用多個Screen,因為每個Screen使用獨立的線程。
問題:
當一個BB程序里有很多個screen時,在堆棧里管理維護它們是一件很困難的事情。
例如,我們在頁面跳轉,更換screen時,將yigge新的screen壓入棧中。
但也許,某些時候有要回到原來的某個screen。
這個時候,我們不能再壓入同一個screen的相同實例。如前所述,VM會拋出一個運行時異常。
那么,我可以生成同一個screen的一個新的實例,壓入棧頂。這樣可以得到一個新的需要的screen,但是新的剛初始化的。
和那個在棧里的screen并非相同的實例有著不同的數據狀態。
解決:
這里的解決方法是:
1 維持一個對象池(object pool),用于維護各個screen的實例。
當客戶需要一個之前的screen時,對象池給予客戶它維護著的對應的screen實例。
當客戶要求的是一個新的頁面的時候,它也能產生新的screen。
在產生新的screen的時候,應該用新的screen覆蓋對象池中的維護的同類的screen舊有實例。
這樣,就可以很靈活地得到一個screen的新的實例,或者得到一個screen之前的實例(用于前一次該頁面的顯示)。
2 而在 BlackBerry 的顯示棧,任何時候只維持棧頂的一個screen。
3 需要顯示某頁時,在 對象池中找到對應的的 screen ,壓入到顯示棧。
頁面轉換的時候,先將之前的screen從棧中彈出,再壓入新的screen。
net.rim.device.api.ui.UiApplication 是用于管理screen的類。
popScreen(Screen screen) 用于彈出棧頂的screen,更新并顯示棧中的下一個screen。
pushScreen(Screen screen) 用于壓入一個screen,更新并顯示這個screen。
net.rim.device.api.ui.Screen 類本身也可以控制自己的彈出。
close() 用于彈出本身,但是有一個附加動作,要是本身是棧中最后一個screen,那么程序也將退出。
這個解決辦法里,棧里只維持一個screen。我們彈出這個screen后棧為空,但我們并不想退出程序,而是想壓入新的screen。
所以,棧操作都由UiApplication來完成。在這個解決辦法里。
實例:

import app.ui.factory.*;

public class ScreenPool
{

private static BusyScreen busyScreen;
public static BusyScreen getBusyScreen( int type )
{
if( type == BusyScreen.TYPE_SYNC )
busyScreen = new BusyScreen( BusyScreen.TYPE_SYNC );
else


return busyScreen;
}


{










{




第一次壓入, 因為棧為空無須彈出screen,以后每次壓棧都先彈出棧內唯一的screen, 使棧為空再壓入新的screen:
pushScreen( ScreenPool.getBusyScreen( BusyScreen.TYPE_NORMAL ) );
或者
pushScreen( ScreenPool.getBusyScreen( BusyScreen.TYPE_SYNC) );
以后每次壓入:
UiApplication.getUiApplication().popScreen();
UiApplication.getUiApplication().pushScreen( ScreenPool.getNewIntervListe());
或者
UiApplication.getUiApplication().popScreen();
UiApplication.getUiApplication().pushScreen( ScreenPool.getPreviousIntervListe());
或者
UiApplication.getUiApplication().popScreen();
UiApplication.getUiApplication().pushScreen( ScreenPool.getBusyScreen( BusyScreen.TYPE_NORMAL ) );