LuckyLuke
LuckyLuke

Reputation: 49107

Activity indicator and threads blackberry

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

Upvotes: 0

Views: 1649

Answers (2)

Laepdjek
Laepdjek

Reputation: 1809

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.

Upvotes: 2

Vivek Kumar Srivastava
Vivek Kumar Srivastava

Reputation: 2158

Find this thread

Blackberry - Loading/Wait screen with animation

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

Upvotes: 0

Related Questions