首页 > 代码库 > 可交互的AsyncTask

可交互的AsyncTask

内网一个牛人写的,感觉挺好,原生的AsyncTask把业务逻辑和UI展示的逻辑都掺和到了一起,这个哥们弄了几个接口,进行了拆分。

public interface IJob{
    public boolean isCancelled();
    public void cancelJob(boolean interrupt);
}
public interface IUiCallback<Result>{
    public void onPreExecute();
    public void onPostExecute(Result result);
    public void onProgressUpdate(Integer... values);
    public void onCancelled();
}
public interface IBusinessCallback<Result>{
    public Result onBusinessLogic(IJob job, Object... params);
}
为了简化调用,派生出两个子类:

public abstract class IBusinessSimpleCallback<Result> implements IBusinessCallback<Result>{
	
	public Result onBusinessLogic(IJob job, Object... params){
		Result result = doBusinessLogic(job, params);
		if(job.isCancelled()){
			return null;
		}else {
			return result;
		}
	}
	
	public abstract Result doBusinessLogic(IJob job, Object... params);
}
public abstract class IUiSimpleCallback<Result> implements IUiCallback<Result>{

	@Override
	public void onPreExecute() {
	}

	@Override
	public void onProgressUpdate(Integer... values) {
	}

	@Override
	public void onCancelled() {
	}
}
这样,UI回调可以只关注onPostExecute,业务回调在cancel之后返回null。

核心类:

public class JobAsyncTask<Result> extends AsyncTask<Object, Integer, Result> implements IJob {
    
    private IUiCallback<Result> mUiCallback;
    private IBusinessCallback<Result> mBizCallback;

    public JobAsyncTask(IBusinessCallback<Result> bizCallback, IUiCallback<Result> uiCallback){
        mUiCallback = uiCallback;
        mBizCallback = bizCallback;
    }

    @Override
    protected Result doInBackground(Object... params){
        return mBizCallback.onBusinessLogic(this, params);
    }

    
    @Override
    protected void onPreExecute(){
        super.onPreExecute();
        mUiCallback.onPreExecute();
    }
    
    @Override
	protected void onPostExecute(Result result) {
		super.onPostExecute(result);
		mUiCallback.onPostExecute(result);
	}

	@Override
	protected void onProgressUpdate(Integer... values) {
		super.onProgressUpdate(values);
		mUiCallback.onProgressUpdate(values);
	}

	@Override
	public void cancelJob(boolean interrupt) {
		this.cancel(interrupt);
	}
}
把AsyncTask生命周期事件分别对应到UI回调和业务回调。

public class ConcurrentMgr {

	public static <Result> IJob submitJob(IBusinessCallback<Result> bizCallback, IUiCallback<Result> uiCallback, Object... params){
        JobAsyncTask<Result> job = new JobAsyncTask<Result>(bizCallback, uiCallback);
        return (IJob)job.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
    }

}

这里还是使用了AsyncTask的线程池,话说executeOnExecutor()竟然可以返回AsyncTask本身,这个比较有用!

现在来看一下,我们的业务组件该如何来写:

public class BusinessLogic {

	public <Result> IJob doSomeBusiness(IUiCallback<Result> uiCallback, final Object someParam){
		IBusinessCallback<Result> bizCallback = new IBusinessSimpleCallback<Result>(){
            @Override
            public Result doBusinessLogic(IJob job, Object... params){
                // do your business here.
            	int num = (Integer)someParam;
            	List<String> list = new ArrayList<String>();
            	for(int i=0;i<num;i++){
            		try{
                		Thread.sleep(500);
                	}catch(Exception e){}
            		list.add("str"+i);
            	}
            	return (Result)list;
            }
        };
        return ConcurrentMgr.submitJob(bizCallback, uiCallback, someParam);
    }

}
我在这里仅仅是生成了2个字符串,然后返回出去。在Activity中可以这样调用:

btn.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				IUiCallback<List<String>> mUiCallback = new IUiSimpleCallback<List<String>>(){
					@Override
					public void onPostExecute(List<String> result) {
						if(result != null){
							for(String str : result){
								Log.e("test", str);
								Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
							}
						}
					}
				};
				IJob mJob = new BusinessLogic().doSomeBusiness(mUiCallback,2);
				try{
					Thread.sleep(500);
				}catch(Exception e){
					e.printStackTrace();
				}
				// mJob.cancelJob(true);
			}
		});

最后,为了让Acitivity销毁时能自动停止job,可以在onDestroy()中cancel任务:

@Override
public void onDestroy(){
    	if(null != mJob) {
		mJob.cancel(true);
	}
}

上面可以看出来,代码很干净整洁,完美地进行了分层,非常的优雅!


可交互的AsyncTask