我正在开发一个项目,我从网上下载一个文件,它并不大,只有一些KB。
我的布局是一个列表,下面有一个标签。当用户更新时(检查新文件是否可用),我想用 Activity 指示器替换标签。
我在单独的线程中下载文件,以免阻塞主线程。但我对 Activity 指示器有疑问。我使用 UiApplication.getUiApplication().invokeLater(//CODE);
从管理器中删除标签并添加 Activity 指示器并启动它。它是否正确?我是在文件下载线程中完成的,是不是需要从主线程调用GUI代码?
然后我有代码块(所有这些都在文件下载线程的运行方法内),它下载报告然后我有一个新的 invokeLater
方法,它删除 Activity 指示器并添加再次贴上标签。
但是,这并不能按预期工作,因为最后一个 invokeLater 代码在第一个代码之前运行。我已经用对话框进行了测试。我该如何解决这个问题?
我希望它按照我编码的顺序运行代码,并且在另一端之前不运行任何代码。我怎样才能做到这一点?
(是的,我知道这很困惑!)
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();
}
});
}
}
最佳答案
如果您看到 invokeLater
runnables 以错误的顺序运行,那么您似乎有三个选择:
- 继续使用invokeLater,并存储一些 boolean 字段(或一些等效字段),告诉您下载是否完成以及 Activity 指示器是否显示。在您的第一个
invokeLater
中,您只会在下载尚未完成时显示指示器;在第二个invokeLater
中,您只需删除已显示的指示器。 - 使用
invokeAndWait
而不是invokeLater
。invokeAndWait
将尽快调用 runnable,并停止当前线程的执行,直到调用 runnable。这将减少将发生的并行化量,但无论如何更改字段都是一个快速操作,因此在这种情况下应该不会太重要 - 不要将
invokeAndWait
与Runnable
一起使用,而是在添加和删除的代码周围使用synchronized(Application.getEventLock())
block 字段。只要在应用程序的事件锁上进行同步,您甚至可以在 UI 线程之外操作 UI。 This article详细讨论一下事件锁。
我会推荐第三个选项,因为它是最强大的。但是,您应该注意,某些操作(例如弹出模式对话框)只能从 UI 线程完成(仅持有事件锁是不够的)。在这些情况下,您需要选择其他两个选项之一。但是,从您描述您尝试执行的操作的方式来看,在这种情况下持有事件锁应该足够了。
关于java - Activity 指示器和线程黑莓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6513557/