インタラクティブなAsyncTask

4927 ワード

内网は1人の牛人が书いて、感じはとても良くて、原生の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);
}
呼び出しを簡略化するために、2つのサブクラスが派生する.
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);
			}
		});

最後に、Activity破棄時にjobを自動的に停止させるために、onDestroy()でcancelタスクをキャンセルできます.
@Override
public void onDestroy(){
    	if(null != mJob) {
		mJob.cancel(true);
	}
}

上から見ると、コードがきれいできれいで、完璧に階層化されていて、とても優雅です!