关于异步任务串行执行的思考与实现
最近在做的一个需求被产品的各种奇葩要求和各种为了体验的迷之借口搞得面目前非,里面有很多异步请求,而且有时候是独立执行,有时候需要相互依赖的串行执行(A的结果回来了,成功的话执行B,不成功不管)。一开始我都是非常简单的在Activity中实现各种回调接口,然后在回调方法中调用下一个异步请求,为了能串行的执行,因此加了很多boolean值标记当前什么状态。然后我就想做一个可以封装异步任务,然后按照顺序异步执行的一个模式。
我希望使用的时候,可以new一个AsyncTask对象,然后它成功的后执行什么,失败的后执行什么这样封装好。用起来大概是这个样子:
1 TaskA taskA = new TaskA(); 2 TaskB taskB = new TaskB(); 3 TaskC taskC = new TaskC(); 4 taskA.success(tastB).failure(taskC);
于是我就写了一个这样的东西:
public abstract class AsyncTask { private static final int EXEC_TYPE_TASK = 1; private static final int EXEC_TYPE_RUNNABLE = 2; private int mAfterSuccessExecWhat = EXEC_TYPE_TASK; private int mAfterFailureExecWhat = EXEC_TYPE_TASK; private AsyncTask mAfterSuccessTask = null; private AsyncTask mAfterFailureTask = null; private Runnable mAfterSuccessRunnable = null; private Runnable mAfterFailureRunnable = null; public final void start() { onBegin(); onWork(); } protected void onBegin() { } protected abstract void onWork(); protected void onEndSuccess(Object ... object) { switch (mAfterSuccessExecWhat) { case EXEC_TYPE_TASK: if (mAfterSuccessTask != null) { mAfterSuccessTask.start(); } break; case EXEC_TYPE_RUNNABLE: if (mAfterSuccessRunnable != null) { mAfterSuccessRunnable.run(); } break; } } protected void onEndFailure(Object ... object) { switch (mAfterFailureExecWhat) { case EXEC_TYPE_TASK: if (mAfterFailureTask != null) { mAfterFailureTask.start(); } break; case EXEC_TYPE_RUNNABLE: if (mAfterFailureRunnable != null) { mAfterFailureRunnable.run(); } break; } } public final AsyncTask afterSuccessExec(AsyncTask nextTask) { mAfterSuccessTask = nextTask; mAfterSuccessExecWhat = EXEC_TYPE_TASK; return this; } public final AsyncTask afterFailureExec(AsyncTask nextTask) { mAfterFailureTask = nextTask; mAfterFailureExecWhat = EXEC_TYPE_TASK; return this; } public final AsyncTask afterSuccessRun(Runnable runnable) { mAfterSuccessRunnable = runnable; mAfterSuccessExecWhat = EXEC_TYPE_RUNNABLE; return this; } public final AsyncTask afterFailureRun(Runnable runnable) { mAfterFailureRunnable = runnable; mAfterFailureExecWhat = EXEC_TYPE_RUNNABLE; return this; } }
然后,假设有两个任务,一个是检测异常,就是传一些参数,然后发起一个网络请求,让后台的逻辑来判断是否异常并且返回。另一个是发起一个创建请求。这些属于业务逻辑部分,就简单的写下。
public class YourEngine { interface OnExceptionResultCallback { void onResult(int errorCode); } interface OnCreateAttendanceResultCallback { void onResult(int errorCode); } public static void requestException(int data, OnExceptionResultCallback callback) { System.out.println("开始检测异常"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("网络回调过来"); if (data == 100) { if (callback != null) { callback.onResult(0); } } else { if (callback != null) { callback.onResult(1); } } } public static void requestCreateAttendance(int data, OnCreateAttendanceResultCallback callback) { System.out.println("开始创建考勤"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("网络回调过来"); if (data == 100) { if (callback != null) { callback.onResult(0); } } else { if (callback != null) { callback.onResult(1); } } } }
然后,接下来有两种场景,第一种是检测异常的请求可以单独发送。另一种是先发送检测异常的请求,如果返回成功,那么再发送创建考勤的请求,否则的话则什么都不干。
如果按原始的方式来搞,我需要在第一个回调中做判断是否需要进行下一个异步任务。这样就比较恶心了,一堆布尔值很烦。
所以,搞出了上面这个AsyncTask之后,工作就简单了。用起来的时候,就像这样:
CheckExceptionTask checkExceptionTask = new CheckExceptionTask(); CreateAttendanceTask createTask = new CreateAttendanceTask(); checkExceptionTask.afterSuccessExec(createTask).afterFailureExec(null); checkExceptionTask.start();
这样就是基本的一个实现,用起来就爽了。