Blackberry - Blackberry OS 4.5上的UiApplication.popScreen()问题

时间:2010-08-12 10:33:30

标签: blackberry

我有一个带有屏幕管理器类的应用程序,这会导致一些问题。 应用程序向服务器发出请求以执行搜索并允许用户查看结果。

该应用程序在我们突然拥有的所有操作系统版本上都运行良好 在某些情况下查看屏幕的问题。

当用户执行搜索并等待结果时,会发生这种情况。 在等待结果时,他们按下显示菜单的轨迹球。 显示结果不需要这样,只是用户决定按下它。

当结果从服务器返回时,应自动显示结果屏幕。在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 
}

2 个答案:

答案 0 :(得分:1)

我设法找到的唯一方法就是我在问题中提到的。当我想删除当前屏幕时。我需要检查它是否与活动屏幕相同。如果它不相同,那么我只是删除活动屏幕,直到我到达我正在寻找的屏幕。只有在显示菜单或弹出窗口时才会发生这种情况。此外,我需要将检查添加到我的自定义弹出代码,以确保它不会尝试删除已删除的屏幕。

看起来有点乱,但找不到任何其他选择。

答案 1 :(得分:0)

我们在应用程序中弹出屏幕的方式是显式弹出您想要的屏幕,而不是最顶层的屏幕。这要么需要跟踪堆栈中的哪些屏幕,要么需要一些代码来遍历堆栈中的屏幕并搜索要弹出的特定屏幕。