package com.netease.LDNetDiagnoService; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.ThreadPoolExecutor; import android.os.AsyncTask; import android.os.Handler; import android.os.Message; /** * * @author liujie * * <p> * The most part is copied for {@link AsyncTask}. * * What's we do here is to control the executor and the core * * number of thread parallely. * * <p> * Since Starting with HONEYCOMB, tasks are executed on a single thread * * to avoid common application errors caused by parallel execution. */ public abstract class LDNetAsyncTaskEx<Params, Progress, Result> { private static final int MESSAGE_POST_RESULT = 0x1; private static final int MESSAGE_POST_PROGRESS = 0x2; private static final int MESSAGE_POST_CANCEL = 0x3; private volatile Status mStatus = Status.PENDING; public enum Status { PENDING, RUNNING, FINISHED, } private static final LDNetInternalHandler sHandler = new LDNetInternalHandler(); private final LDNetWorkerRunnable<Params, Result> mWorker; private final FutureTask<Result> mFuture; // protected Hashtable<Params, LDNetAsyncTaskEx> mTaskCache = new // Hashtable<Params, LDNetAsyncTaskEx>(); public LDNetAsyncTaskEx() { mWorker = new LDNetWorkerRunnable<Params, Result>() { public Result call() throws Exception { // Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); return doInBackground(mParams); } }; mFuture = new FutureTask<Result>(mWorker) { @SuppressWarnings("unchecked") @Override protected void done() { Message message; Result result = null; try { result = get(); } catch (InterruptedException e) { android.util.Log.w(this.getClass().getSimpleName(), e); } catch (ExecutionException e) { throw new RuntimeException( "An error occured while executing doInBackground()", e.getCause()); } catch (CancellationException e) { message = sHandler.obtainMessage(MESSAGE_POST_CANCEL, new LDNetAsyncTaskResult<Result>(LDNetAsyncTaskEx.this, (Result[]) null)); message.sendToTarget(); return; } catch (Throwable t) { // throw new RuntimeException( // "An error occured while executing " // + "doInBackground()", t); } message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new LDNetAsyncTaskResult<Result>(LDNetAsyncTaskEx.this, result)); message.sendToTarget(); } }; } private static class LDNetInternalHandler extends Handler { @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public void handleMessage(Message msg) { LDNetAsyncTaskResult result = (LDNetAsyncTaskResult) msg.obj; switch (msg.what) { case MESSAGE_POST_RESULT: // There is only one result result.mTask.finish(result.mData[0]); break; case MESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; case MESSAGE_POST_CANCEL: result.mTask.onCancelled(); break; } } } public final Status getStatus() { return mStatus; } protected abstract Result doInBackground(Params... params); /** * 后台线程准备运行阶段 */ protected void onPreExecute() { } /** * 后台运行阶段,当前运行已经结束 * @param result */ protected void onPostExecute(Result result) { } /** * 进度更新阶段 * @param values */ protected void onProgressUpdate(Progress... values) { } /** * 取消运行 */ protected void onCancelled() { } public final boolean isCancelled() { return mFuture.isCancelled(); } public final boolean cancel(boolean mayInterruptIfRunning) { return mFuture.cancel(mayInterruptIfRunning); } /** * 初始化运行阶段 * @param params * @return */ @SuppressWarnings("incomplete-switch") public final LDNetAsyncTaskEx<Params, Progress, Result> execute(Params... params) { if (mStatus != Status.PENDING) { switch (mStatus) { case RUNNING: throw new IllegalStateException("Cannot execute task:" + " the task is already running."); case FINISHED: throw new IllegalStateException("Cannot execute task:" + " the task has already been executed " + "(a task can be executed only once)"); } } mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params; ThreadPoolExecutor sExecutor = getThreadPoolExecutor(); // ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, // MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, // sThreadFactory); if (sExecutor != null) { sExecutor.execute(mFuture); return this; } else { return null; } } protected abstract ThreadPoolExecutor getThreadPoolExecutor(); protected final void publishProgress(Progress... values) { sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new LDNetAsyncTaskResult<Progress>(this, values)).sendToTarget(); } protected void finish(Result result) { if (isCancelled()) { result = null; } onPostExecute(result); mStatus = Status.FINISHED; } private static abstract class LDNetWorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; } private static class LDNetAsyncTaskResult<Data> { @SuppressWarnings("rawtypes") final LDNetAsyncTaskEx mTask; final Data[] mData; LDNetAsyncTaskResult(@SuppressWarnings("rawtypes") LDNetAsyncTaskEx task, Data... data) { mTask = task; mData = data; } } }