刷新屏幕以使用新数据更新ListField

时间:2012-12-27 13:19:15

标签: blackberry java-me

我正在使用ListField Control来显示从xml webservice返回的数据。我想每分钟刷新ListField或屏幕,以使用新记录或数据更新ListField。

我尝试使用下面的代码,但它无法正常工作(它挂起)。

public MyApp() {
    // Push a screen onto the UI stack for rendering.
    UiApplication.getUiApplication().invokeLater(new Runnable() {
        public void run() {
            UiApplication.getUiApplication().pushScreen(new MyScreen());
        }
    },5000,true);
}
ResponseHandler handler = new ResponseHandler();
ListField listUsers = new ListField(handler.getItem().size());

public MyScreen() {
    setTitle("yQAforum");
    //Fetch the xml from the web service
    String wsReturnString = GlobalV.Fetch_Webservice("myDs");
    //Parse returned xml
    SAXParserImpl saxparser = new SAXParserImpl();
    ByteArrayInputStream stream = new ByteArrayInputStream(wsReturnString.getBytes());
    try {
        saxparser.parse( stream, handler );
    } 
    catch ( Exception e ) {
        response.setText( "Unable to parse response.");
    }
    //Return vector sze from the handler class
    listUsers.setSize(handler.getItem().size());
    listUsers.setCallback(this);
    listUsers.setEmptyString("No Users found", 0);
    add(listUsers);
}

1 个答案:

答案 0 :(得分:2)

您正在尝试从UI线程上的Web服务获取数据。这几乎总是错误的。

UI线程(也称为线程)负责绘制UI,跟踪用户操作,如触摸或通过触控板/轨迹球导航。如果阻止UI线程等待远程Web服务器响应,则它无法为UI提供服务。

你应该做一些改变:

public MyApp() {
    // Push a screen onto the UI stack for rendering.
    UiApplication.getUiApplication().invokeLater(new Runnable() {
        public void run() {
            UiApplication.getUiApplication().pushScreen(new MyScreen());
        }
    },5000,true);
}

应改为

public MyApp() {
    // Push a screen onto the UI stack for rendering.
    pushScreen(new MyScreen());
}

已经在UI线程上调用MyApp()构造函数,因此无需使用invokeLater()在UI线程上执行pushScreen()调用。如果在MyApp构造函数中运行,它已经在UI线程上调用。此外,5000毫秒的延迟并没有多大帮助。这只会将您的应用启动延迟5秒,用户会讨厌。

如果您尝试实施启动画面或其他类似功能,当应用启动时,请搜索堆栈溢出“BlackBerry启动画面”,我相信您会找到结果。

现在,一旦创建了MyScreen类,您应该注意而不是从UI线程获取Web服务结果。 MyScreen构造函数将在UI线程上运行。如果需要,您可以在显示屏幕后在后台线程上启动 Web服务请求。一种方法是使用onUiEngineAttached()

protected void onUiEngineAttached(boolean attached) {
    if (attached) {
        // TODO: you might want to show some sort of animated
        //  progress UI here, so the user knows you are fetching data

        Timer timer = new Timer();
        // schedule the web service task to run every minute
        timer.schedule(new WebServiceTask(), 0, 60*1000);
    }
}

public MyScreen() {
    setTitle("yQAforum");

    listUsers.setEmptyString("No Users found", 0);
    listUsers.setCallback(this);
    add(listUsers);
}

private class WebServiceTask extends TimerTask {
    public void run() {
        //Fetch the xml from the web service
        String wsReturnString = GlobalV.Fetch_Webservice("myDs");
        //Parse returned xml
        SAXParserImpl saxparser = new SAXParserImpl();
        ByteArrayInputStream stream = new ByteArrayInputStream(wsReturnString.getBytes());
        try {
           saxparser.parse( stream, handler );
        } 
        catch ( Exception e ) {
           response.setText( "Unable to parse response.");
        }
        // now, update the UI back on the UI thread:
        UiApplication.getUiApplication().invokeLater(new Runnable() {
           public void run() {
              // TODO: record the currently selected, or focused, row

              //Return vector sze from the handler class
              listUsers.setSize(handler.getItem().size());
              // Note: if you don't see the list content update, you might need to call
              //   listUsers.invalidate();
              // here to force a refresh.  I can't remember if calling setSize() is enough.

              // TODO: set the previously selected, or focused, row
           }
        });
    }
}

如果网络服务没有响应,或者需要花费超过一分钟的时间,您需要添加一些错误处理(如果最后一个尚未完成,您将不希望发出新请求)。

但是,这应该让你开始。

注意:一旦解决了在UI线程上运行网络代码的问题,您可能仍然发现您的代码无效。获取Web服务数据可能会出现问题。你必须调试它。我只向您展示发布的代码一个问题。如果您仍然遇到Web服务提取问题,请发布另一个问题(修复了UI线程问题)。感谢。