使用AysncTask而不是Thread之前有个博文专门讲了传送门。
可是在使用AysncTask还是有诸多不便。
1. 每个任务都写一个AysncTask类,太违背重用代码的理念
2. 需要写一堆传入参数
3. 如果一个java类中需要多种后台任务,不同的AysncTask写出来以后使得java篇幅太长
我还是希望:
1. 重用重复代码
2. 不以任务名字写AysncTask内部类
3. 有个统一的启动任务入口
4. 将任务和处理任务的AysncTask分开来,任务可以用一个 final int 来区分
思考之后我是这么做的,给出思路图并贴出代码,能力有限敬听大家意见。
图中左侧是分离出来的任务处理类 右侧是具体任务启动和实现类
/**
* Created by lzc on 2017/10/10.
*/
public class AsyncTaskExecutor {
//饥饿 随类加载
private static AsyncTaskExecutor ourInstance = new AsyncTaskExecutor();
//一个Activity 或者Service中不会有太多的任务 用稀疏key-value:SparseArray
//保存任务号和任务引用
private SparseArray<SeedTask> ayncTaskMapper = new SparseArray<>();
public static AsyncTaskExecutor getInstance() {
return ourInstance;
}
private AsyncTaskExecutor() {
}
//关注传入实体和任务号
/**
*
*Entity 是web bean的基类
*/
public void forkTaskAndExecute(Entity entity, int task, UiAsyncTaskCallBack uiAsyncTaskCallBack) {
if (ayncTaskMapper.get(task) != null) {
Log.d("lzc", task + "异步任务正在执行");
return;
}
//不去持有Activity的强引用
SeedTask seedTask = new SeedTask(entity, task, new WeakReference(uiAsyncTaskCallBack));
ayncTaskMapper.put(task, seedTask);
seedTask.execute((Void) null);
}
//重载方法 只关注后台逻辑
public void forkTaskAndExecute(UiAsyncTaskCallBack uiAsyncTaskCallBack) {
forkTaskAndExecute(null,0,uiAsyncTaskCallBack);
}
class SeedTask extends AsyncTask<Void, Void, Response> {
private Entity entity;
private int task;
private WeakReference<UiAsyncTaskCallBack> uiAsyncTaskCallBack;
SeedTask(Entity entity, int task, WeakReference<UiAsyncTaskCallBack> uiAsyncTaskCallBack) {
this.entity = entity;
this.task = task;
this.uiAsyncTaskCallBack = uiAsyncTaskCallBack;
}
@Override
protected Response doInBackground(Void... params) {
if(uiAsyncTaskCallBack.get() == null){
return null;
}
return uiAsyncTaskCallBack.get().doInBackgroud(task, entity);
}
@Override
protected void onPreExecute() {
uiAsyncTaskCallBack.get().onPreExecute(task);
}
@Override
protected void onPostExecute(final Response response) {
if(response != null){
ayncTaskMapper.remove(task);
uiAsyncTaskCallBack.get().onPostExecute(task, response);
}
}
@Override
protected void onCancelled() {
ayncTaskMapper.remove(task);
}
}
}
/**
* Created on 2017/10/10.
* Entity 起初想用泛型 但是具体UiAsyncTaskCallBack实现者的任务类型不确定
* 所以为web实体加了统一父类 用作具体情况下的强制转型
*
*/
public interface UiAsyncTaskCallBack{
void onPreExecute(int task);
Response doInBackgroud(int task, Entity entity);
void onPostExecute(int task, Response asyncResult);
}
//如果任务类型单一 可以用泛型省掉强制转型
public interface UiAsyncTaskCallBack<T>{
void onPreExecute(int task);
T doInBackgroud(int task, T entity);
void onPostExecute(int task, T asyncResult);
}
网络任务种类比较繁杂我建立了一个接口来统一保存
public interface AysncTaskList {
int LOGIN = 2001;
int REGISTE = 2002;
...
}
我们的Activity既可以这样来发起一个任务:
Activity implements UiAsyncTaskCallBack
//类内任务
AsyncTaskExecutor.getInstance().forkTaskAndExecute(LOAD_DATA,this);
//网络任务
User user = newUser(P,N);
AsyncTaskExecutor.getInstance().forkTaskAndExecute(user ,USER_LOGIN,this);
当然网络任务如何处理user 的login是另外一个流程了,在这不表了。
Response doInBackgroud(int task, Entity entity){
//打开case 来分别处理
switch(task){
}
return response;//统一封装的返回类
}
void onPostExecute(int task, Response asyncResult){
//打开case 来分别处理
switch(task){
}
}
over
刚芭蕾!