使用SwingWorker之二

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();
            text = "Image unavailable";
   
發佈了4 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章