package com.imyeyu.fx.task; import javafx.concurrent.Service; import javafx.concurrent.Task; import com.imyeyu.java.bean.Callback; import com.imyeyu.java.bean.CallbackArg; import com.imyeyu.java.bean.CallbackReturn; /** * 异步线程执行,常用的构建异步线程任务 * *
 *     // 快速构造
 *     RunAsync.run(() -> {});           // 快速异步执行 {@link #run(Callback)}
 *     RunAsync.run(() -> {}, () -> {}); // 快速异步回调 {@link #run(Callback, Callback)}
 *     RunAsync.run(() -> 100, v -> {}); // 快速异步返回 {@link #callbackReturn(CallbackReturn, CallbackArg)}
 *     RunAsync.later(() -> {}, 1000);   // 延时一秒执行 {@link #later(Callback, long)}
 *
 *     // 标准构造
 *     new RunAsync<T>() {
 *
 *         @Override
 *         protected T call() throws Exception {
 *
 *             // 这里不是 FX 线程,可以执行一些长时间的事情
 *
 *             update(new T()); // 主动更新数据
 *             progress(.6);    // 更新进度
 *             return new T();  // 返回更新数据
 *         }
 *
 *         @Override
 *         protected void onUpdate(T t) {
 *             // 数据更新事件,属于 FX 线程,视 UI 线程状态回调
 *         }
 *
 *         @Override
 *         protected void onUpdateProgress(double progress) {
 *             // 更新进度事件,属于 FX 线程,视 UI 线程状态回调
 *         }
 *
 *         @Override
 *         protected void onFinish() {
 *             // 线程执行完成,属于 FX 线程
 *         }
 *
 *         @Override
 *         protected void onException(Throwable e) {
 *             // 线程异常,属于 FX 线程
 *         }
 *     }.start();  <-- 千万别忘了启动任务
 * 
* * @author 夜雨 * @since 2021-02-13 12:56 * @param 数据处理返回类型 */ public abstract class RunAsync extends Service { /** 任务对象 */ protected PublicTask task; /** 最近一次更新数据 */ protected T lastT; protected boolean isInterrupted = false; @Override protected Task createTask() { task = new PublicTask<>() { protected T call() throws Exception { return RunAsync.this.call(); } }; task.setOnScheduled(e -> isInterrupted = false); task.setOnSucceeded(e -> { onFinish(); onFinish(lastT); onFinally(); isInterrupted = false; }); task.setOnFailed(e -> { onFinally(); isInterrupted = false; }); task.valueProperty().addListener((obs, o, t) -> { lastT = t; onUpdate(t); }); task.messageProperty().addListener((obs, o, msg) -> onMessage(msg)); task.progressProperty().addListener((obs, o, p) -> onProgress(p.doubleValue())); task.exceptionProperty().addListener((obs, o, e) -> onException(e)); return task; } /** * 执行事件(非 FX 线程) * * @return 处理结果 * @throws Exception 处理异常 */ protected abstract T call() throws Exception; /** * 主动更新数据,通常是非 FX 线程的 call 里触发,{@link #onUpdate(T)} 里视 UI 线程状态回调 * * @param t 更新值 */ protected void update(T t) { lastT = t; task.updateValue(t); } /** * 主动更新进度,非 FX 线程的 call 里触发,{@link #onProgress(double)} 里视 UI 线程状态回调 * * @param progress 进度值 */ protected void progress(double progress) { task.updateProgress(progress, 1); } /** * 更新消息,非 FX 线程的 call 里触发,{@link #onMessage(String)} 里视 UI 线程状态回调 * * @param msg 消息 */ protected void message(String msg) { task.updateMessage(msg); } /** * 数据更新事件,{@link #update(T)} 或 {@link #call()} 返回参数触发,属于 FX 线程 * * @param t 更新数据 */ protected void onUpdate(T t) { // 子类实现 } /** * 更新进度事件,{@link #progress(double)} 触发,属于 FX 线程 * * @param progress 进度值 */ protected void onProgress(double progress) { // 子类实现 } /** * 更新消息 * * @param msg 消息 */ protected void onMessage(String msg) { // 子类实现 } /** 完成事件(FX 线程,只要线程结束就会调用) */ protected void onFinish() { // 子类实现 } /** * 完成事件(FX 线程,只要线程结束就会调用,参数为 {@link #update(T)} 或 {@link #call()} 最后一次更新值) * * @param t 执行事件返回值 */ protected void onFinish(T t) { // 子类实现 } /** * 发生异常(FX 线程) * * @param e 异常 */ protected void onException(Throwable e) { e.printStackTrace(); } /** 线程完成监听,无论正常完成还是出现异常,都会触发此方法 */ protected void onFinally() { // 子类实现 } /** 中断任务 */ public void interrupt() { isInterrupted = true; cancel(); } // ---------- 静态构造 ---------- /** * 快速构造稍后执行,触发事件属于 FX 线程 * * @param callback 异步事件 * @param delay 延时时间(毫秒) */ public static void later(Callback callback, long delay) { run(() -> { try { Thread.sleep(delay); } catch (InterruptedException e) { e.printStackTrace(); } }, callback); } /** * 快速构造异步任务 * * @param callback 异步回调 */ public static void run(Callback callback) { run(callback, null, null); } /** * 快速构造异步任务 * * @param asyncCallback 异步回调 * @param finishCallback 异步完成回调 */ public static void run(Callback asyncCallback, Callback finishCallback) { run(asyncCallback, finishCallback, null); } /** * 快速构造异步任务 * * @param asyncCallback 异步回调 * @param exceptionCallback 异常回调 */ public static void run(Callback asyncCallback, CallbackArg exceptionCallback) { run(asyncCallback, null, exceptionCallback); } /** * 快速构造异步任务(私有为了可读性,既然主要事件都用上了那应该使用 new {@link RunAsync}() 来保持可读性) * * @param asyncCallback 异步回调 * @param finishCallback 异步完成回调 * @param exceptionCallback 异常回调 */ private static void run(Callback asyncCallback, Callback finishCallback, CallbackArg exceptionCallback) { new RunAsync() { @Override protected Void call() { asyncCallback.handler(); return null; } @Override protected void onFinish() { try { if (finishCallback != null) { finishCallback.handler(); } } catch (Exception e) { e.printStackTrace(); } } @Override protected void onException(Throwable e) { if (exceptionCallback != null) { exceptionCallback.handler(e); } } }.start(); } /** * 快速构造异步任务 * * @param asyncCallback 异步回调 * @param finishCallback 异步完成回调 * @param 回调数据类型 */ public static void callbackReturn(CallbackReturn asyncCallback, CallbackArg finishCallback) { new RunAsync() { @Override protected T call() { return asyncCallback.handler(); } @Override protected void onFinish(T t) { finishCallback.handler(t); } }.start(); } }