package com.minggo.pluto.common;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
import com.google.gson.Gson;
import com.minggo.pluto.util.LogUtils;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 异步任务
*
* @param <Params>
* @param <Progress>
* @param <Result>
* @author minggo
* @time 2014-12-29上午10:14:21
*/
public abstract class CommonAsyncTask<Params, Progress, Result> implements Observer {
private static final String TAG = "CommonAsyncTask";
private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 5;
private static final int KEEP_ALIVE = 10;
private static final BlockingQueue<Runnable> sWorkQueue = new ArrayBlockingQueue<Runnable>(120);
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "CommonAsyncTask #" + mCount.getAndIncrement());
}
};
private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE,
KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory, new ThreadPoolExecutor.DiscardOldestPolicy());
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
private static final int MESSAGE_POST_CANCEL = 0x3;
/**
* 同一个UI线程中的消息队列只有在UI线程空闲前不再往消息队列添加消息时队列才开始处理消息
*/
private static final InternalHandler sHandler = new InternalHandler();
private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;
private volatile Status mStatus = Status.PENDING;
protected Gson gson = new Gson();
public enum Status {
/**
* 等待运行的线程.
*/
PENDING,
/**
* 运行中的线程.
*/
RUNNING,
/**
* 运行完毕的线程.
*/
FINISHED,
}
/**
* 创建一个新的线程. 被界面主线程调用.
*/
public CommonAsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return doInBackground(mParams);
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
Message message;
Result result = null;
try {
if (isCancelled()) {
message = sHandler.obtainMessage(MESSAGE_POST_CANCEL, new UserTaskResult<Result>(
CommonAsyncTask.this, (Result[]) null));
message.sendToTarget();
//System.out.println("CommonAsyncTask cancel----------------------->");
return;
}
result = get();
} catch (InterruptedException e) {
LogUtils.error(TAG, e.toString());
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()", e.getCause());
} catch (CancellationException e) {
message = sHandler.obtainMessage(MESSAGE_POST_CANCEL, new UserTaskResult<Result>(
CommonAsyncTask.this, (Result[]) null));
message.sendToTarget();
// System.out.println("CommonAsyncTask cancel----------------------->");
return;
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing " + "doInBackground()", t);
}
message = sHandler.obtainMessage(MESSAGE_POST_RESULT, new UserTaskResult<Result>(CommonAsyncTask.this,
result));
message.sendToTarget();
}
};
}
/**
* 返回当前线程的状态.
*
* @return The current status.
*/
public final Status getStatus() {
return mStatus;
}
/**
* 此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用.
* 后台进程执行的具体计算在这里实现,doInBackground
* (Params...)是AsyncTask的关键,此方法必须重载。在这个方法内可以使用
* publishProgress(Progress...)改变当前的进度值。
*/
protected abstract Result doInBackground(Params... params);
/**
* 执行预处理,它运行于UI线程,可以为后台任务做一些准备工作,比如绘制一个进度条控件。
*
* @see #onPostExecute(Object)
* @see #doInBackground(Object[])
*/
protected void onPreExecute(Params... params) {
}
/**
* 此方法在主线程执行,任务执行的结果作为此方法的参数返回。
* 运行于UI线程,可以对后台任务的结果做出处理,结果就是doInBackground(Params
* ...)的返回值。此方法也要经常重载,如果Result为null表明后台任务没有完成(被取消或者出现异常)。
*/
@SuppressWarnings({"UnusedDeclaration"})
protected void onPostExecute(Result result) {
}
/**
* 运行于UI线程。如果在doInBackground(Params...)中使用了publishProgress(Progress...),
* 就会触发这个方法。在这里可以对进度条控件根据进度值做出具体的响应。
*/
@SuppressWarnings({"UnusedDeclaration"})
protected void onProgressUpdate(Progress... values) {
}
/**
* 在界面主线程并在cancel(boolean) 之后调用.
*
* @see #cancel(boolean)
* @see #isCancelled()
*/
protected void onCancelled() {
AppContext.getInstance().getAsyncTaskManager().deleteObserver(this);
}
/**
* 如果当前任务在正常完成之前被取消返回 true
*
* @see #cancel(boolean)
*/
public final boolean isCancelled() {
return mFuture.isCancelled();
}
/**
* 如果未开始运行则会被取消运行,如果已经运行则会跑出mayInterruptIfRunning错误并终止运行
*
* @param mayInterruptIfRunning 如果为true 如果线程正在执行则会被中断,否则,会等待任务完成。
* @return false 如果线程无法取消,很可能是因为已经完成 true 则相反
* @see #isCancelled()
* @see #onCancelled()
*/
public final boolean cancel(boolean mayInterruptIfRunning) {
return mFuture.cancel(mayInterruptIfRunning);
}
/**
* 返回结果
*/
public final Result get() throws InterruptedException, ExecutionException {
return mFuture.get();
}
/**
* 在制定时间内等待结果,超出时间则取消任务
*/
public final Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException,
TimeoutException {
return mFuture.get(timeout, unit);
}
/**
* 自动调用的回调参数
*
* @param params task的需要的参数.
* @return 返回一个task的实例.
*/
public final CommonAsyncTask<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(params);
mWorker.mParams = params;
AppContext.getInstance().getAsyncTaskManager().addTask(this);
sExecutor.execute(mFuture);
return this;
}
/**
* 此方法在doInBackground(Object[])里面 当后台计算在运行时在UI线程调用
* 每次调用都会触发通过onProgressUpdate()方法在UI线程显示出来
*
* @param values UI线程需要的参数
* @see # onProgressUpdate (Object[])
* @see #doInBackground(Object[])
*/
protected final void publishProgress(Progress... values) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS, new UserTaskResult<Progress>(this, values)).sendToTarget();
}
private void finish(Result result) {
onPostExecute(result);
mStatus = Status.FINISHED;
AppContext.getInstance().getAsyncTaskManager().deleteObserver(this);
}
private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
UserTaskResult result = (UserTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// 只有一个返回
if (result.mTask.isCancelled()) {
result.mTask.cancel(true);
//System.out.println("CommonAsyncTask cancel----------------------->");
break;
}
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
case MESSAGE_POST_CANCEL:
result.mTask.cancel(true);
break;
}
}
}
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
@SuppressWarnings({"RawUseOfParameterizedType"})
private static class UserTaskResult<Data> {
final CommonAsyncTask mTask;
final Data[] mData;
UserTaskResult(CommonAsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
@Override
public void update(Observable o, Object arg) {
if (AsyncTaskManager.CANCEL_ALL == (Integer) arg) {
if (getStatus() == CommonAsyncTask.Status.RUNNING) {
cancel(true);
}
}
}
}