バックグラウンド IO がビジー状態のときにアニメーションの進行状況インジケーターを表示するビジー レイヤーを作成しました。Gluon モバイル 4 のガラス板にレイヤーが追加されます。
BusyLayer extends Layer { ...
root = new FlowPane(new ProgressIndicator());
MobileApplication.getInstance().getGlassPane().getLayers().add(this);
DH2FX extends MobileApplication { ...
addLayerFactory("Busy", () -> new BusyLayer());
...
showLayer("Busy");
...
hideLayer("Busy");
Gluon 5 では getLayers が削除され、移行ガイドに従ってレイヤーを直接表示できます。
BusyLayer extends Layer { ...
root = new FlowPane(new ProgressIndicator());
DH2FX extends MobileApplication { ...
BusyLayer busyLayer = new BusyLayer();
...
busyLayer.show();
...
busyLayer.hide();
ただし、レイヤーは非表示ではありません。
====
メイン プレーヤーはシングルトンの Background クラスであるため、BusyLayer は 1 回だけ表示されます。
class BackgroundActivity {
private final AtomicInteger busyAtomicInteger = new AtomicInteger(0);
BusyLayer busyLayer = new BusyLayer();
private long time;
public BackgroundActivity() {
busyLayer.setOnShowing(e -> {
time = System.currentTimeMillis();
System.out.println("Showing busyLayer");
});
busyLayer.setOnShown(e -> {
System.out.println("busyLayer shown in: " + (System.currentTimeMillis() - time) + " ms");
});
busyLayer.setOnHiding(e -> System.out.println("hiding layer at " + (System.currentTimeMillis() - time) + " ms"));
}
void start() {
if (busyAtomicInteger.getAndIncrement() == 0) {
busyLayer.show();
}
}
void done() {
if (busyAtomicInteger.decrementAndGet() == 0) {
busyLayer.hide();
}
}
void failure(Throwable t) {
t.printStackTrace();
failure();
}
void failure() {
done();
}
}
protected final BackgroundActivity backgroundActivity = new BackgroundActivity();
そして、CompletableFutures を使用して非同期タスクを実行する次のようなコードを作成します。
// Hours
backgroundActivity.start();
CompletableFuture.supplyAsync( () -> entryService().getHours(calendarPickerForHessian))
.exceptionally( e -> { backgroundActivity.failure(e); return null; } )
.thenAcceptAsync( (Hour[] hours) -> {
Platform.runLater( () -> {
refreshHours(hours);
backgroundActivity.done();
});
});
// ProjectTotals
backgroundActivity.start();
CompletableFuture.supplyAsync( () -> entryService().getProjectTotals(calendarPickerForHessian) )
.exceptionally( e -> { backgroundActivity.failure(e); return null; } )
.thenAcceptAsync( (LinkedHashMap<Integer, Double> projectTotals) -> {
Platform.runLater( () -> {
refreshProjectTotals(projectTotals);
backgroundActivity.done();
});
});
// DayTotals
backgroundActivity.start();
CompletableFuture.supplyAsync( () -> entryService().getDayTotals(calendarPickerForHessian))
.exceptionally( e -> { backgroundActivity.failure(e); return null; } )
.thenAcceptAsync( (SortedMap<String, Double> dayTotals) -> {
Platform.runLater( () -> {
refreshDayTotals(dayTotals);
backgroundActivity.done();
});
});
もちろん、BusyLayer 自体:
public class BusyLayer extends Layer {
public BusyLayer() {
root = new StackPane(new ProgressIndicator());
root.setAlignment(Pos.CENTER);
root.getStyleClass().add("semitransparent7");
getChildren().add(root);
}
private final StackPane root;
@Override
public void layoutChildren() {
root.setVisible(isShowing());
if (!isShowing()) {
return;
}
GlassPane glassPane = MobileApplication.getInstance().getGlassPane();
root.resize(glassPane.getWidth(), glassPane.getHeight());
resizeRelocate(0, 0, glassPane.getWidth(), glassPane.getHeight());
}
}