0

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();
                }
            });
        }
    }
LuckyLuke
  • 47,771
  • 85
  • 270
  • 434
  • the event thread keeps a queue of actions to run, so the ordering on your invoke later runnables should be preserved. How did you determine the second one runs first? Try adding a debug print out. – Michael Donohue Jun 29 '11 at 14:55

2 Answers2

2

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.

Laepdjek
  • 1,779
  • 12
  • 6
  • invokeAndWait has no greater scheduling priority than invokeLater. The only difference is invokeAndWait blocks, while invokeLater does not. – Michael Donohue Jun 29 '11 at 14:49
  • Also, the event thread does process events in order. There is no guaranteed maximum wait time, but ordering is preserved. However, waiting for the application event lock with synchronized(...) does not have any ordering guarantee, as now it is up to the OS scheduler who wins the lock contention. – Michael Donohue Jun 29 '11 at 14:57
  • @MichaelDonohue : So in this example, the first invokeAndWait or synchronized would block until it completed, and hence the second invokeAndWait or synchronized would not be executed until the first one was completed, achieving exactly what Andreas asked for... – Laepdjek Jun 29 '11 at 17:05
  • Michael is correct that the events should still be processed in the order that you queue them. The above solutions will still work to ensure that everything is done in the correct order, but it would also be worth investigating to see if the two runnables are actually being run in the incorrect order, or if something else is going on. – Laepdjek Jun 29 '11 at 17:30
0

Find this thread

Blackberry - Loading/Wait screen with animation

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

Community
  • 1
  • 1
Vivek Kumar Srivastava
  • 2,158
  • 1
  • 16
  • 23