背景: 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来完成。在这个解决办法里。
实例:
第一次压入, 因为栈为空无须弹出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 ) );