Async in JavaFX 1.2

JavaFX 1.2 になって 非同期処理用API が一新されたので ちょっと試してみました。

と言うのも...
前回の記事で紹介した SQLite を本気で JavaFX で利用するためには、DBとのやりとりを非同期化しなくてはならないからです。
DB の処理の度にアプリケーションが止まっていたら全く使い物になりません...


今回試したサンプルは、『ついにベールを脱いだJavaFX 第11回 通信と非同期処理』で紹介されていた JavaFX 1.1 用のコードを ただ単に JavaFx 1.2 に変更しただけのものです。

JavaFX 1.2 でコーディングしてみた感想ですが...
今回のAPIの変更で非常に使いやすくなったと思います。
と言うより...
やっと使えるものになったという感じでしょうか。

JavaFX 1.1 では javafx.async 以外のクラスを利用しないと実装できないというかなり苦しい仕様でしたが、JavaFX 1.2 からは javafx.async のみで実装できるようになり、かなりスッキリした仕様になったと思います。
ただ、相変わらず 非同期処理部分は java でコーディングしないといけないのが少し残念ですが、これは実装次第でなんとかなりそうな気がしますので今後検討していきたいと思います。


以下、変更点を簡単にまとめました。

LongLongTaskImpl.java

変更点:

  • com.sun.javafx.runtime.async.AbstractAsyncOperation ではなく javafx.async.RunnableFuture を実装するようになった。
  • com.sun.javafx.runtime.async.AbstractAsyncListener がなくなった。
  • Callable から Runnable 相当のインターフェースになった。(処理結果をメソッドの戻り値として返せなくなった。)
import java.util.Date;
import javafx.async.RunnableFuture;

public class LongLongTaskImpl implements RunnableFuture {

    private Date result;

    public LongLongTaskImpl(Date result) {
        this.result = result;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(10000L);
        } catch (InterruptedException ex) {}

        result.setTime(System.currentTimeMillis());
    }
}

LongLongTask.fx

変更点:

  • AbstractAsyncOperation ではなく JavaTaskBase を拡張するようになった。
  • create() で RunnableFuture の実装クラスのインスタンスを生成して返すだけで良くなった。
  • onCompletion(value: Object) がなくなった。(RunnableFuture は Callable ではないので当然だが 処理結果が取得できなくなった。)
import javafx.async.JavaTaskBase;
import java.util.Date;

public class LongLongTask extends JavaTaskBase {

    public-read var result = new Date();
    var task: LongLongTaskImpl;

    override function create() {
        task = new LongLongTaskImpl(result);
    }
}

Main.fx の一部 変更した箇所

変更点:

  • インスタンス生成後に start() をコールしないと実行されなくなった。
  • onDone の引数がなくなった。
Timeline {
    repeatCount: Timeline.INDEFINITE
    autoReverse: true
    keyFrames: [
        KeyFrame {
            time: 0s
            action: function() {
            	// 非同期処理クラスを生成し、非同期処理を開始する
                var task: LongLongTask;
                task = LongLongTask {
                    // 非同期処理後にコールされる関数
                    onDone: function() : Void {
                        result = task.result;
                    }
                }
                task.start();
            }
        },
        KeyFrame {
            time: 5s
        }
    ]
}.play();