Проблема многопоточности Blackberry - PullRequest
0 голосов
/ 11 января 2012

Я разрабатываю приложение BlackBerry, которое связывается с сервером через HTTP-запросы (javax.microedition.io.HttpConnection). На устройстве пользователь щелкает некоторые элементы пользовательского интерфейса, и устройство отправляет запросы на сервер. Когда приходит ответ, пользовательский интерфейс изменяется. Связь происходит под новым потоком, в то время как поток пользовательского интерфейса выдвигает и выдает ProgressDialogScreen.

Проблема иногда в том, что когда приходит ответ и выдается ProgressDialogScreen, пользовательский интерфейс не изменяется, но через пару секунд пользовательский интерфейс меняется. Если вы запросили в промежутке между появлением ProgressDialogScreen и нажатием нового экрана, возникает беспорядок. Первый самый старый новый экран нажимается, и самый новый новый экран нажимается. И эту ситуацию можно наблюдать как сервер, отвечающий на неправильные запросы. Эта проблема возникает на симуляторе и устройстве.

Другая проблема, иногда два одинаковых ответа возвращаются для одного запроса. Мне удалось увидеть эти две проблемы на симуляторе в журналах, но я не смог увидеть эту проблему на устройстве, так как я не вижу журналы.

EDIT:

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();
}

Кстати, ProgressBar расширяется с net.rim.device.api.ui.container.PopupScreen, а Stoppable расширяется с Runnable

.

Ответы [ 3 ]

1 голос
/ 20 января 2012

Я предпочел выскочить индикатор выполнения после того, как новый экран подготовлен и нажат. Таким образом, между запросом и ответом не будет нового запроса.

0 голосов
/ 16 января 2012

Похоже, что вы анализируете в потоке пользовательского интерфейса. Пожалуйста, удалите Vector accounts = Parser.parse(utf8Response,Parser.ACCOUNTS); из пользовательского потока и сделайте это в отдельном потоке.

0 голосов
/ 12 января 2012

Почему бы не сделать:

private static void progress(final Stoppable runThis, String text,boolean cancelable) {
    progress = new ProgressBar(runThis, text,cancelable);
    UiApplication.getUiApplication().pushScreen(progress);
    [...]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...