Activity indicator and threads blackberry

老子叫甜甜 提交于 2019-12-08 13:48:14

问题


I am working on a project where I download from a file from the web, it is not big only some KBs.

My layout is a list with a label below it. When the user updates (checks if new file is available) I want to replace the label with the activity indicator.

I download the file in a separate thread to not block the main thread. But I have problems with the activity indicator. I use UiApplication.getUiApplication().invokeLater(//CODE); to remove the label from the manager and add the activity indicator, as well as starting it. Is this correct? I do it in the file downloading thread, and isnt it right that you need to invoke GUI code from the main thread?

then I have block of code (all of this is inside the run method of the file downloading thread) which downloads the report then I have a new invokeLater method which removes the activity indicator and adds the label again.

However this does not work as expected since the last invokeLater code is run before the first one. I have tested with dialogs. How could I solve this?

I want it to run the code in the order in I coded it in, and no code run before the other ends. How could I accomplish that?

(and yes, I know this is messy!)

private class UpdateReportThread extends Thread {
        public void run() {
            super.run();

            UiApplication.getUiApplication().invokeLater(new Runnable() {
                public void run() {
                    view = new ActivityIndicatorView(Field.FIELD_HCENTER);
                    model = new ActivityIndicatorModel();
                    controller = new ActivityIndicatorController();

                    view.setController(controller);
                    view.setModel(model);
                    controller.setModel(model);
                    controller.setView(view);
                    model.setController(controller);    

                    Bitmap bitmap = Bitmap.getBitmapResource("spinner.jpg");
                    view.createActivityImageField(bitmap, 5, Field.FIELD_HCENTER);

                    dialogManager = new VerticalFieldManager(Manager.FIELD_HCENTER | Manager.FIELD_VCENTER | Manager.USE_ALL_HEIGHT);
                    dialogManager.add(new LabelField("Please wait...", Field.FIELD_HCENTER));
                    dialogManager.add(view);

                    add(dialogManager);     
                    view.getModel().resume();

                    delete(lblIssueWeek);
                    delete(lblIssueYear);
                }
            });


            //File downloading code
                    //File downloading code
                    //File downloading code    

            UiApplication.getUiApplication().invokeLater(new Runnable() {
                public void run() {
                    view.getModel().cancel();
                    delete(dialogManager);

                    lblIssueWeek = new LabelField("", LabelField.FIELD_HCENTER);
                    lblIssueYear = new LabelField("", LabelField.FIELD_HCENTER);
                    add(lblIssueWeek);
                    add(lblIssueYear);
                    updateCurrentIssue();
                }
            });
        }
    }

回答1:


If you are seeing invokeLater runnables being run in the incorrect order, then it seems like you have three options:

  1. Continue to use invokeLater, and store some boolean fields (or some equivalent) that tell you whether the download is complete, and whether the activity indicator is showing. In your first invokeLater, you would only show the indicator if the download has not completed; and in your second invokeLater, you would only remove the indicator if it has been shown.
  2. Use invokeAndWait instead of invokeLater. invokeAndWait will call the runnable as soon as possible, and will halt execution in the current thread until the runnable has been called. This will reduce the amount of parallelization that will occur, but changing fields is a quick operation anyway so that shouldn't matter too much in this case
  3. Instead of using invokeAndWait with a Runnable, use a synchronized(Application.getEventLock()) block around the code that adds and removes fields. You can manipulate the UI even outside of the UI thread, so long as you are synchronized on the application's event lock. This article talks a little bit more about event locks.

I would recommend the third option, since it is the most robust. However, you should be aware that there are certain operations, such as popping up a modal dialog box, that can only be done from the UI thread (holding the event lock is not sufficient). In those cases, you would need to go with one of the other two options. However, from the way you described what you are trying to do, holding the event lock should be sufficient in this situation.




回答2:


Find this thread

Blackberry - Loading/Wait screen with animation

this is the good example to show the please wait indicator.



来源:https://stackoverflow.com/questions/6513557/activity-indicator-and-threads-blackberry

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!