在Java / J2ME中与UI线程交互
我正在编写一个J2ME应用程序。 其中一个部分定期轮询目录的内容,如果有任何新内容,则在屏幕上绘制它们。 我已经通过让UI表单启动一个带有指针返回自身的轮询线程来完成此操作,并且当轮询线程找到它回调到表单并调用syncrhonized方法来更新它的显示时。 这似乎工作正常。
我的问题是这个。 在C#/ .NET中我知道让非UI线程更新UI并不好,处理它的正确方法是将其委托给UI线程。
例如以下内容:
public void DoSomeUIThing() { if (this.uiComponent.InvokeRequired) { this.uiComponent.Invoke(someDelegateThatCallsBackToThis); } else { this.uiComponent.Text = "This is the update I want to happen"; } }
有关于如何管理此过程的J2ME等价物吗? Java怎么样? 或者Java / J2ME在这方面做得更好? 如果没有,这是怎么做到的?
[编辑]看来Swing支持我通过SwingUtilities.invokeLater()和invokeAndWait()方法询问的内容。 是否有J2ME的等效框架?
关于Java,您所描述的内容看起来像SwingWorker(工作线程) 。
当Swing程序需要执行长时间运行的任务时,它通常使用一个工作线程,也称为后台线程。
Swing程序包括以下类型的线程:
- 初始线程,执行初始应用程序代码的线程。
- 事件派发线程,执行所有事件处理代码。 大多数与Swing框架交互的代码也必须在此线程上执行。
- 工作线程,也称为后台线程,执行耗时的后台任务。
单线程规则 :
一旦实现了Swing组件,所有可能影响或依赖于该组件状态的代码都应该在事件派发线程中执行。
在J2EE上下文中使用时,在从EJB引用SwingWorker时需要小心。
关于J2ME ,这取决于您是将您的应用程序开发为可在任何启用MIDP的设备上运行的标准MIDlet,还是作为RIMlet开发,这是一个基于CLDC的应用程序,它使用BlackBerry特定的API,因此仅在BlackBerry上运行设备。
因为与MIDP的UI类不同,RIM类似于Swing,因为UI操作发生在事件线程上,这在MIDP中不是线程安全的。 要在事件线程上运行代码,应用程序必须获取对事件对象的锁定,或使用invokeLater()或invokeAndWait() – 为开发人员提供额外的工作,但复杂性带有价格标签。
但是对于LCDUI ,您可以从多个线程访问表单 。
Java ME有很多配置文件。 如果你的意思是MIDP,那么Display.runSerially
就是你想要的。
对于AWT(Swing),你可以使用EventQueue.invokeLater
( SwingUtilities.invokeLater
只是必需的,因为Java 1.1没有EventQueue
方法 – 1.2即将庆祝它的十岁生日)。 对于Common DOM API,请使用DOMService.invokeLater
。
无论GUI API如何声称线程安全,它们可能都是错误的(在JDK7中删除了一些Swing的声明,因为它们不可实现)。 在任何情况下,应用程序代码都不太可能是线程安全的。
对于j2me应用程序,您可能希望保持简单。 主要是仅在事件线程中触摸UI组件。 这样做的直接方法是使用invokeLater或invokeAndWait 。 根据您的库,您将无法访问除此之外的任何内容。 一般情况下,如果您的平台没有提供这些,它可能等同于没有线程支持而不是问题。 例如,黑莓确实支持它 。
如果在SWT下开发,则可以通过Display对象的asyncExec()方法实现。 您传递实现Runnable的对象,以便UI线程执行在其他线程中完成的更改。
这是从这里借来的一个例子
public void itemRemoved(final ModelEvent me) { final TableViewer tableViewer = this.viewer; if (tableViewer != null) { display.asyncExec(new Runnable() { public void run() { tableViewer.remove(me.getItem()); } } } }
我可以certificateMIDP UI工具包确实是线程安全的,因为我有几乎所有制造商生产的数百万部手机上运行复杂GUI的大型MIDlet,我从未在这方面遇到过问题。