我有一个带有屏幕管理器类的应用程序,这会导致一些问题。 应用程序向服务器发出请求以执行搜索并允许用户查看结果。
该应用程序在我们突然拥有的所有操作系统版本上都运行良好 在某些情况下查看屏幕的问题。
当用户执行搜索并等待结果时,会发生这种情况。 在等待结果时,他们按下显示菜单的轨迹球。 显示结果不需要这样,只是用户决定按下它。
当结果从服务器返回时,应自动显示结果屏幕。在OS 4.5上,代码显示结果屏幕运行,但随后应用程序完全崩溃。如果用户在等待时没有按下轨迹球,则应用程序正常工作。
查看日志,它们显示没有抛出异常,唯一的可疑行是
System data:VM:DPNAv=78,p
通过添加更多日志行,我发现代码正在到达 。UiApplication.getUiApplication()popScreen(屏幕); 方法hideScreen(屏幕屏幕)中的行但是从hideCurrentScreen()调用时。通过添加一些更多的调试,我发现此时活动屏幕是DefaultMenuScreen(因为已按下菜单按钮)
所以似乎问题是我试图从显示器弹出我自己的一个屏幕 当DefaultMenuScreen是活动的一个时,堆栈。我再说一遍,这段代码确实适用于4.5之前的操作系统。通过使用调试语句在带有OS 4.2.2的8300上运行相同的代码,我可以看到同样的事情发生,活动屏幕是DefaultScreen但删除我自己的屏幕不会导致整个应用程序崩溃。
我可以看到的唯一方法是将hideCurrentScreen()更改为仅删除活动屏幕,但这似乎不是正确的方法。
有没有其他人有这方面的经验?谁能告诉我为什么会这样?如果我们在DefaultMenuScreen是活动屏幕时无法移除屏幕,我们打算做什么?
这在8310和9700的设备和模拟器中都会发生。
屏幕管理器代码如下。
public class ScreenManager
{
private Hashtable screens;
private String currentScreenName;
public ScreenManager()
{
screens=new Hashtable();
}
/**
* Description of the Method
*
*@param sCardName Description of Parameter
*/
public boolean showScreen( String sScreenName )
{
boolean bSuccess=false;
if (sScreenName != null && sScreenName.length() > 0 )
{
MainScreen screen=(MainScreen)screens.get(sScreenName);
if (screen!=null)
{
// We have a new screen to display so pop the current screen off the stack
hideCurrentScreen();
// If the screen is on the stack then pop the screens until we get our target screen
// otherwise just push the screen onto the stack.
if (screen.isDisplayed())
{
Screen activeScreen=null;
synchronized(UiApplication.getEventLock())
{
activeScreen=UiApplication.getUiApplication().getActiveScreen();
}
while (screen!=activeScreen && activeScreen!=null)
{
activeScreen=hideScreen(activeScreen);
}
bSuccess=(screen==activeScreen);
}
else
{
synchronized(UiApplication.getEventLock())
{
UiApplication.getUiApplication().pushScreen(screen);
bSuccess=true;
}
}
}
}
if (bSuccess)
{
this.currentScreenName=sScreenName;
}
else
{
Logger.warning("ScreenManager: Failed to display screen ["+ sScreenName +"]");
}
return bSuccess;
}
private Screen hideCurrentScreen()
{
Screen activeScreen=null;
if(currentScreenName!=null)
{
MainScreen screen=(MainScreen)screens.get(currentScreenName);
activeScreen=hideScreen(screen);
}
return activeScreen;
}
private Screen hideScreen(Screen screen)
{
Screen activeScreen=null;
if (screen!=null && screen.isDisplayed())
{
Logger.finest("Hiding Screen ["+currentScreenName+"]");
synchronized(UiApplication.getEventLock())
{
UiApplication.getUiApplication().popScreen(screen);
activeScreen=UiApplication.getUiApplication().getActiveScreen();
}
Logger.finest("Hid Screen ["+currentScreenName+"]");
}
return activeScreen;
}
//Rest of code omitted
}
答案 0 :(得分:1)
我设法找到的唯一方法就是我在问题中提到的。当我想删除当前屏幕时。我需要检查它是否与活动屏幕相同。如果它不相同,那么我只是删除活动屏幕,直到我到达我正在寻找的屏幕。只有在显示菜单或弹出窗口时才会发生这种情况。此外,我需要将检查添加到我的自定义弹出代码,以确保它不会尝试删除已删除的屏幕。
看起来有点乱,但找不到任何其他选择。
答案 1 :(得分:0)
我们在应用程序中弹出屏幕的方式是显式弹出您想要的屏幕,而不是最顶层的屏幕。这要么需要跟踪堆栈中的哪些屏幕,要么需要一些代码来遍历堆栈中的屏幕并搜索要弹出的特定屏幕。