Reputation: 49107
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
Reputation: 1809
If you are seeing invokeLater
runnables being run in the incorrect order, then it seems like you have three options:
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.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 caseinvokeAndWait
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
Reputation: 2158
Find this thread
Blackberry - Loading/Wait screen with animation
this is the good example to show the please wait indicator.
Upvotes: 0