黑莓多线程问题

时间:2012-01-11 18:16:15

标签: multithreading blackberry

我正在开发一个BlackBerry应用程序,它通过HTTP请求(javax.microedition.io.HttpConnection)与服务器通信。在设备上,用户单击一些UI项,设备将请求发送到服务器,当响应到来时,UI更改。通信在新线程下进行,而UI线程则推送并弹出ProgressDialogScreen。

问题有时候,当响应出现并且弹出ProgressDialogScreen时,UI不会改变,但是几秒钟之后UI会发生变化。如果您在弹出ProgressDialogScreen和推送新屏幕之间请求,则会出现问题。推出第一个最古老的新屏幕,推出最新的新屏幕。这种情况可以像服务器响应错误请求一样被观察到。这个问题发生在模拟器和设备上。

另一个问题是,一个请求有时会返回两个相同的响应。我能够在日志的模拟器上看到这两个问题,但我无法在设备上看到这个问题,因为我看不到日志。

修改

String utf8Response;
HttpConnection httpConn = null;
try{
    httpConn = (HttpConnection) Connector.open(url);
    httpConn.setRequestMethod(HttpConnection.GET);
    httpConn.setRequestProperty("Content-Type", "text/html; charset=UTF8");
    if(sessionIdCookie != null){
        //may throw IOException, if the connection is in the connected state.
        httpConn.setRequestProperty("Cookie", sessionIdCookie);
    }
}catch (Exception e) {
    //...
}

try{
    httpConn.getResponseCode();
    return httpConn;
}catch (IOException e) {
    // ...
}
byte[] responseStr = new byte[(int)httpConn.getLength()];
DataInputStream strm = httpConn.openDataInputStream();
strm.readFully(responseStr);
try{
    strm.close();
}catch (IOException e) {
    // ....
}
utf8Response = new String(responseStr, "UTF-8");

如果此代码成功运行,则会运行此代码并按下新屏幕:

UiApplication.getUiApplication().invokeLater(new Runnable() {
    public void run() {
       Vector accounts = Parser.parse(utf8Response,Parser.ACCOUNTS);
       if (accounts.size() == 0){
           DialogBox.inform(Account.NO_DEPOSIT);
           return;
       }
       currentScreen = new AccountListScreen(accounts);
       changeScreen(null,currentScreen);
    }
});

public void changeScreen(final AbstractScreen currentScreen,final AbstractScreen nextScreen) {
    if (currentScreen != null) 
        UiApplication.getUiApplication().popScreen(currentScreen);
    if (nextScreen != null)
        UiApplication.getUiApplication().pushScreen(nextScreen);
}

EDITv2:

private static void progress(final Stoppable runThis, String text,boolean cancelable) {
    progress = new ProgressBar(runThis, text,cancelable);
    Thread threadToRun = new Thread() {
        public void run() {
            UiApplication.getUiApplication().invokeLater(new Runnable() {
                public void run() {
                    try{
                        UiApplication.getUiApplication().pushScreen(progress);
                    }catch(Exception e){
                        Logger.log(e);
                    }
                }
            });
            try {
                runThis.run();
            } catch (Throwable t) {
                t.printStackTrace();
            }
            UiApplication.getUiApplication().invokeLater(new Runnable() {
                 public void run() {
                    try {
                        UiApplication.getUiApplication().popScreen(progress);
                    } catch (Exception e) { }
                 }
            });
        }
   };
   threadToRun.start();
}

顺便说一下,ProgressBarnet.rim.device.api.ui.container.PopupScreen延伸,StoppableRunnable延伸

3 个答案:

答案 0 :(得分:1)

我准备在准备并推送新屏幕后弹出进度条。这样,请求和响应之间就不会有新的请求。

答案 1 :(得分:0)

为什么不这样做:

private static void progress(final Stoppable runThis, String text,boolean cancelable) {
    progress = new ProgressBar(runThis, text,cancelable);
    UiApplication.getUiApplication().pushScreen(progress);
    [...]

答案 2 :(得分:0)

好像你正在UI线程上进行解析。请从ui线程中删除Vector accounts = Parser.parse(utf8Response,Parser.ACCOUNTS);并在单独的线程中执行。