使用SwingWorker之二(2007-01-29 10:04:40)
SwingWorker基础
本节简要介绍SwingWorker的功能。SwingWorker的定义如下:
public abstract class SwingWorker<T,V> extends Object
implements RunnableFuture
SwingWorker是抽象类,因此必须继承它才能执行所需的特定任务。注意该类有两个类型参数:T及V。T是doInBackground和get方法的返回类型,V是publish和process方法要处理的数据类型。后文将作详细解释。
该类实现了java.util.concurrent.RunnableFuture接口。RunnableFuture接口是Runnable和Future两个接口的简单封装。由于SwingWorker实现了Runnable接口,因此SwingWorker有一个run方法。Runnable对象一般作为线程的一部分执行,当Thread对象启动时,它激活Runnable对象的run方法。由于SwingWorker实现了Future接口,因此SwingWorker产生类型为T的结果值并提供同线程交互的方法。SwingWorker实现以下接口方法:
* boolean
cancel(boolean mayInterruptIfRunning)
* T
get()
* T get(long
timeout, TimeUnit unit)
* boolean
isCancelled()
* boolean
isDone()
SwingWorker实现了所有的接口方法,实际上你仅需要实现以下SwingWorker的抽象方法:
protected T doInBackground() throws Exception
doInBackground方法作为任务线程的一部分执行,它负责完成线程的基本任务,并以返回值来作为线程的执行结果。继承类须覆盖该方法并确保包含或代理任务线程的基本任务。不要直接调用该方法,应使用任务对象的execute方法来调度执行。
在获得执行结果后应使用SwingWorker的get方法获取doInBackground方法的结果。可以在EDT上调用get方法,但该方法将一直处于阻塞状态,直到任务线程完成。最好只有在知道结果时才调用get方法,这样用户便不用等待。为防止阻塞,可以使用isDone方法来检验doInBackground是否完成。另外调用方法get(long
timeout, TimeUnit
unit)将会一直阻塞直到任务线程结束或超时。获取任务结果的最好地方是在done方法内:
protected void done()
在doInBackground方法完成之后,SwingWorker调用done方法。如果任务需要在完成后使用线程结果更新GUI组件或者做些清理工作,可覆盖done方法来完成它们。这儿是调用get方法的最好地方,因为此时已知道线程任务完成了,SwingWorker在EDT上激活done方法,因此可以在此方法内安全地和任何GUI组件交互。
没必要等到线程完成就可以获得中间结果。中间结果是任务线程在产生最后结果之前就能产生的数据。当任务线程执行时,它可以发布类型为V的中间结果,覆盖process方法来处理中间结果。后文还将提供这些方法的更多详细信息。当属性改变时,SwingWorker实例能通知处理器,SwingWorker有两个重要的属性:状态和进程。任务线程有几种状态,以下面SwingWorker.StateValue枚举值来表示:
*
PENDING
*
STARTED
* DONE
任务线程一创建就处于PENDING状态,当doInBackground方法开始时,任务线程就进入STARTED状态,当doInBackground方法完成后,任务线程就处于DONE状态,随着线程进入各个阶段,SwingWorker超类自动设置这些状态值。你可以添加处理器,当这些属性发生变化来接收通知。
最后,任务对象有一个进度属性,随着任务进展时,可以将这个属性从0更新到100标识任务进度,当该属性发生变化时,任务通知处理器进行处理。
实现简单的ImageRetriever
当点击列表所略图时,事件处理器创建了一个ImageRetriever实例并执行之。ImageRetriever下载选中的图片并在列表下面展示它。当实现SwingWorker子类,须指定doInBackground和get方法返回值的类型。因为ImageRetriever并不生成中间结果,它使用特殊类型Void作为中间类型,ImageRetriever的任务的结果是一图片,因此使用Icon类型作为doInBackground和get方法的返回类型,下面代码显示了ImageRetriever的大部分实现:
public class ImageRetriever extends SwingWorker<Icon, Void> {
private
ImageRetriever()
{}
public
ImageRetriever(JLabel lblImage, String strImageUrl) {
this.strImageUrl = strImageUrl;
this.lblImage = lblImage;
}
@Override
protected
Icon doInBackground() throws Exception {
Icon icon = retrieveImage(strImageUrl);
return icon;
}
private Icon
retrieveImage(String strImageUrl)
throws MalformedURLException, IOException
{
InputStream is = null;
URL imgUrl = null;
imgUrl = new URL(strImageUrl);
is = imgUrl.openStream();
ImageInputStream iis = ImageIO.createImageInputStream(is);
Iterator<ImageReader> it =
ImageIO.getImageReadersBySuffix("jpg");
ImageReader reader = it.next();
reader.setInput(iis);
...
Image image = reader.read(0);
Icon icon = new ImageIcon(image);
return icon;
}
@Override
protected
void done() {
Icon icon = null;
String text = null;
try {
icon = get();
} catch (Exception ignore) {
ignore.printStackTrace();