简介
Android的UI工具包不是线程安全工具包,你不能通过工作线程操纵UI,而只能通过UI线程来操作用户界面,单线程模式必须遵守两条规则:
不要阻塞UI线程
不要在UI线程之外访问android的UI工具包
Asynctask可以恰当和容易的使用UI线程.这个类允许执行后台操作然后发布结果到UI线程而不需要处理线程和handler.
Asynctask被用作线程和handler的一个辅助类,不构成通用的线程框架.理论上它适合简短的操作(最多几秒),如果你需要让线程跑很长一段时间,你最好去使用java.util.concurrent包中提供的Executor,ThreadPoolExecutor和Futuretask.
Asynctask有3个泛型参数(Params,Progress,Result),4个执行步骤(onPreExecute,doInBackground,onProgressUpdate和onPostExecute).
Asynctask 相比 thread 和handler 更加轻量级一点。
使用
首先继承Asynctask<Params,Progress,Result>
类 ,并至少实现doInBackground(..)
范型参数说明:
Params:后台任务的输入参数,比如http请求的目标url
Progress:后台任务执行的进度
Result:后台任务返回的结果,比如Api调用返回的json数据
方法:
onPreExecute(), UI线程调用,在后台任务执行前调用,可以做一些准备工作,可以不实现。
doInBackground(Params…),工作线程执行,耗时的任务写在这里,必须实现。在这个方法里可以调用publishProgress方法来更新后台任务的实时进度,计算返回的结果将被传递给onPostExecute方法.
onProgressUpdate(Progress…),UI线程执行,在publishProgress方法(工作线程中)被调用后,UI线程调用它来显示任务的进度,如在进度条上显示,或textView上显示百分比。
onPostExecute(Result),UI线程调用,doInBackground()执行完成后被调用,后台任务执行的结果传递到这里当做参数。
onCancelled(),UI线程调用,有两个,有参数(doInBackground返回的数据)或无参数,
返回
主动调用asynctask的cancel方法,他会执行完doInBackground方法,然后执行onCancelled方法,不执行onPostExecute方法了。(为了尽快取消一个任务,在doInBackground方法中“定期检查”isCancelled()是否为true ,若为true 直接返回。比如在一个循环中)
注意事项
asynctask一个实例只能execute一次。(asynctask有个状态变量,Status(FINISHED,PENDING,RUNNING))
Asynctask类必须在UI线程加载,这时自动完成的.实例必须在UI线程创建,exxcute必须在UI线程调用.
不要手动调用onPreExecute(), onPostExecute(Result), doInBackground(Params…), onProgressUpdate(Progress…)方法.
有参数的onCancelled直接调了无参数的那个函数。
protected void onCancelled(Result result) {
onCancelled();
}
Memory observability(观察内存)
Asynctask保证所有的回调方法的调用都是同步的,所以以下操作在没有明确同步情况下是安全的.
在构造函数或onPreExecute()中设置成员变量,然后在doInBackground()使用.
在doInBackground()中设置成员变量,然后在onProgressUpdate()和onPostExecute()中使用.
执行方式(并行还是串行)
当第一次被提出,Asynctask是在一个单独后台线程串行执行的.从Android.1.6开始,变成了一个允许多任务并行执行的线程池.从Android.3.0开始,为了避免并行执行引发的常见应用程序错误,任务在一个单独线程执行.
如果你想并行执行,你可以调用executeOnExecutor() 利用参数 THREAD_POOL_EXECUTOR.这个方法返回一个本身的一个引用.你也可以自己定义线程池.
public static ExecutorService exec = Executors.newFixedThreadPool(10);
并行执行可能导致修改顺序出错(写入文件),导致数据丢失和稳定性问题.所以最好是串行执行,无论android版本,你可以和 SERIAL_EXECUTOR 一起使用.
源码解析
从执行起点开始,execute方法:
//使用默认执行器 SERIAL_EXECUTOR
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
//这个方法设置执行器.
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
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 继承了callable接口的抽象类
mWorker.mParams = params;
exec.execute(mFuture); //futuretask类型
return this;
}
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override //在mworker的call方法执行完做的事情
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj; //携带运算结果和asynctask对象的一个对象.
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;
}
}
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
private static class AsyncTaskResult<Data> {
final AsyncTask mTask;
final Data[] mData;
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
使用线程执行runnable之后无法获得结果,使用callable加future可以传回运算结果(先执行call方法,调用futuretask的get()方法可以获得结果,会阻塞线程到得到结果). futuretask继承runnableFuture接口.
execute(mfuture) 会先执行它里面的callable对象,也就是继承了callable的workerRunnable的call方法,里面会执行doInBackground方法并获得结果,然后 postResult(result)获取handler发送消息,what变量为MESSAGE_POST_RESULT,根据what变量来采取不同的操作,最后还有一个finish方法.