読者です 読者をやめる 読者になる 読者になる

Swing Application Framework その5:タスク管理


GUIアプリケーションにおいて、長時間を要する処理は event dispatch thread (EDT)とは別スレッドで実行する必要がります。フレームワークは、このバックグラウンドスレッド処理の始動、停止、モニタの機能を提供します。
Java SE 6 から提供された SwingWorker はこの機能を提供しますが、Task は実際 SwingWorker を継承し、より高機能となっています。
Task クラスは Task の実行、TaskMonitor クラスは Task のモニタリング機能を提供します。ここでは Task の基本的な使用方法に絞って説明します。

使用方法

最も簡単な Task の利用方法は、Task クラスのサブクラスを作成していくつかのメソッドをオーバーライドし、これを Action ハンドラと共に使用します。これにより、タスクの進行状況をモニタリングすることができます。
Task を継承したカスタムタスクを作成し、doInBackground メソッドをオーバーライドして、その中でバックグラウンドで実施する処理を行います。

Taskの使用例

Task のサブクラスとして NetworkTimeRetriever クラスを作成し、doInBackground メソッドをオーバーライドしています。また、Task クラスはコミュニケート用のいくつかのメソッドを定義していますが、この中の1つの succeeded メソッドをオーバーライドして、タスクの完了時に結果をテキストフィールドに設定するようになっています。この succeeded メソッドは EDT 上で動作しますので、GUI コンポーネントのアップデート処理等を行うことができます。

public class NetworkTimeApp extends SingleFrameApplication {
    JPanel timePanel;
    JButton btnShowTime;
    JTextField txtShowTime;

    @Override
    protected void startup() {
        ActionMap map = getContext().getActionMap(this);
        javax.swing.Action action = map.get("retrieveTime");
        btnShowTime.setAction(action);
        timePanel.add(btnShowTime);
        timePanel.add(txtShowTime);
        show(timePanel);
    }

    @Action
    public Task retrieveTime() {
        Task task = new NetworkTimeRetriever(this);
        return task;
    }

    class NetworkTimeRetriever extends Task<Date, Void> {

        public NetworkTimeRetriever(Application app) {
            super(app);
        }

        @Override
        protected Date doInBackground() throws Exception {
            // long-running task
            Date now = dateFormat.parse(strDate);
            return now;
        }

        @Override
        protected void succeeded(Date time) {
            txtShowTime.setText(time.toString());
        }
    }
}

Action アノテーションメソッド retrieveTime() が Task を返却することに注意して下さい。このメソッドは、Task のサブクラスの NetworkTimeRetriever のインスタンスを作成して返却します。フレームワークは、この Task を自動的にバックグラウンドスレッドで走らせ、成功裏に完了すると、succeedes メソッドにてUIを更新します。
Task と Action とリソースインジェクションの組み合わせは、イベントハンドリングを簡単で強力にします。