http://www.blogjava.net/lincode/archive/2008/08/28/225170.html
背景:
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 ) );