AsyncTask
- 三个参数(都可为Void):
Params:参数
Progress:执行进度
Result:返回值 - 四个方法 :
onPreExecute() 主线程执行,异步方法执行前调用。
doInBackground(Params...params) 线程池中执行,用于执行异步任务;在方法内部用publishProgress 来更新任务进度。
onProgressUpdate(Progress...value)主线程执行,后台任务进度状态改变时被调用。
onPostExecute(Result result) 主线程执行,异步任务执行之后被调用
执行顺序: onPreExecute->doInBackground->onPostExecute 如果取消了异步任务,会回调onCancelled(),onPostExecute则不会被调用
Tips: AsyncTask的类必须在主线程加载,Android4.1及以上已经被系统自动完成了;AsyncTask对象必须在主线程创建;execute方法需要在UI线程调用;一个AsyncTask对象只能调用一次;Android1.6之前串行执行,Android1.6采用线程池并行处理任务,Android3.0开始,采用一个线程执行任务,但也可以通过executeOnExecutor方法来并行执行任务
AsyncTask的工作原理
先看一段示例:
package com.example.zhy_asynctask_demo01;import android.app.Activity;import android.app.ProgressDialog;import android.os.AsyncTask;import android.os.Bundle;import android.util.Log;import android.widget.TextView;public class MainActivity extends Activity{private static final String TAG = "MainActivity";private ProgressDialog mDialog;private TextView mTextView;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mTextView = (TextView) findViewById(R.id.id_tv);mDialog = new ProgressDialog(this);mDialog.setMax(100);mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);mDialog.setCancelable(false);new MyAsyncTask().execute();}private class MyAsyncTask extends AsyncTask<Void, Integer, Void>{@Overrideprotected void onPreExecute(){mDialog.show();Log.e(TAG, Thread.currentThread().getName() + " onPreExecute ");}@Overrideprotected Void doInBackground(Void... params){// 模拟数据的加载,耗时的任务for (int i = 0; i < 100; i++){try{Thread.sleep(80);} catch (InterruptedException e){e.printStackTrace();}publishProgress(i);}Log.e(TAG, Thread.currentThread().getName() + " doInBackground ");return null;}@Overrideprotected void onProgressUpdate(Integer... values){mDialog.setProgress(values[0]);Log.e(TAG, Thread.currentThread().getName() + " onProgressUpdate ");}@Overrideprotected void onPostExecute(Void result){// 进行数据加载完成后的UI操作mDialog.dismiss();mTextView.setText("LOAD DATA SUCCESS ");Log.e(TAG, Thread.currentThread().getName() + " onPostExecute ");}}}
进入某个Activity,Activity中需要的数据来自于网络或者其它耗时操作,可以在AsyncTask中onPreExecute完成一些准备操作,比如上例中显示进度对话框;然后在doInBackground完成耗时操作,在进行耗时操作时还能不时的通过publishProgress给onProgressUpdate中传递参数,然后在onProgressUpdate中可以进行UI操作,比如上例更新进度条的进度;当耗时任务执行完成后,最后在onPostExecute进行设置控件数据更新UI等操作,例如隐藏进度对话框。

源码解析
那么大家一定好奇,AsyncTask在Android中是如何实现的,下面进行源码分析:从我们的执行异步任务的起点开始,进入execute方法:
public final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}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.mParams = params;exec.execute(mFuture);return this;}
18行:设置当前AsyncTask的状态为RUNNING,上面的switch也可以看出,每个异步任务在完成前只能执行一次。
20行:执行了onPreExecute(),当前依然在UI线程,所以我们可以在其中做一些准备工作。
22行:将我们传入的参数赋值给了mWorker.mParams
23行:exec.execute(mFuture)
相信大家对22行出现的mWorker,以及23行出现的mFuture都会有些困惑。
mWorker找到这个类:
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 uncheckedreturn postResult(doInBackground(mParams));}};//….}
private Result postResult(Result result) {@SuppressWarnings("unchecked")Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,new AsyncTaskResult<Result>(this, result));message.sendToTarget();return result;}
private static class AsyncTaskResult<Data> {final AsyncTask mTask;final Data[] mData;AsyncTaskResult(AsyncTask task, Data... data) {mTask = task;mData = data;}}
看到这,我相信大家肯定会想到,在某处肯定存在一个sHandler,且复写了其handleMessage方法等待消息的传入,以及消息的处理。
private static final InternalHandler sHandler = new InternalHandler();private static class InternalHandler extends Handler {@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})@Overridepublic void handleMessage(Message msg) {AsyncTaskResult result = (AsyncTaskResult) msg.obj;switch (msg.what) {case MESSAGE_POST_RESULT:// There is only one resultresult.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;}
mWoker看完了,应该到我们的mFuture了,依然实在构造方法中完成mFuture的初始化,将mWorker作为参数,复写了其done方法。
public AsyncTask() {...mFuture = new FutureTask<Result>(mWorker) {@Overrideprotected void done() {try {postResultIfNotInvoked(get());} catch (InterruptedException e) {android.util.Log.w(LOG_TAG, e);} catch (ExecutionException e) {throw new RuntimeException("An error occured while executing doInBackground()",e.getCause());} catch (CancellationException e) {postResultIfNotInvoked(null);}}};}
private void postResultIfNotInvoked(Result result) {final boolean wasTaskInvoked = mTaskInvoked.get();if (!wasTaskInvoked) {postResult(result);}}
好了,到了这里,已经介绍完了execute方法中出现了mWorker和mFurture,不过这里一直是初始化这两个对象的代码,并没有真正的执行。下面我们看真正调用执行的地方。
execute方法中的:
还记得上面的execute中的23行:exec.execute(mFuture)
exec为executeOnExecutor(sDefaultExecutor, params)中的sDefaultExecutor
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;public static final Executor SERIAL_EXECUTOR = new SerialExecutor();private static class SerialExecutor implements Executor {final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();Runnable mActive;public synchronized void execute(final Runnable r) {mTasks.offer(new Runnable() {public void run() {try {r.run();} finally {scheduleNext();}}});if (mActive == null) {scheduleNext();}}protected synchronized void scheduleNext() {if ((mActive = mTasks.poll()) != null) {THREAD_POOL_EXECUTOR.execute(mActive);}}}
16-17行:判断当前mActive是否为空,为空则调用scheduleNext方法
20行:scheduleNext,则直接取出任务队列中的队首任务,如果不为null则传入THREAD_POOL_EXECUTOR进行执行。
下面看THREAD_POOL_EXECUTOR为何方神圣:
public static final Executor THREAD_POOL_EXECUTOR=new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
//现在已经根据CPU内核数目来设置线程池的大小了.
private static final int CORE_POOL_SIZE = 5;private static final int MAXIMUM_POOL_SIZE = 128;private static final int KEEP_ALIVE = 1;private static final ThreadFactory sThreadFactory = new ThreadFactory() {private final AtomicInteger mCount = new AtomicInteger(1);public Thread newThread(Runnable r) {return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());}};private static final BlockingQueue<Runnable> sPoolWorkQueue =new LinkedBlockingQueue<Runnable>(10);
HandlerThread
- HandlerThread继承了Thread,是一种可以使用Handler的Thread;在run方法中通过looper.prepare()来开启消息循环,这样就可以在HandlerThread中创建Handler了;外界可以通过一个Handler的消息方式来通知HandlerThread来执行具体任务;确定不使用之后,可以通过quit或quitSafely方法来终止线程执行;具体使用场景是IntentService。
2.4 IntentService
- IntentSercie是一种特殊的Service,继承了Service并且是抽象类,任务执行完成后会自动停止,优先级远高于普通线程,适合执行一些高优先级的后台任务;
- IntentService封装了HandlerThread和Handler,onCreate方法自动创建一个HandlerThread,然后用它的Looper构造了一个Handler对象mServiceHandler,这样通过mServiceHandler发送的消息都会在HandlerThread执行;
IntentServiced的onHandlerIntent方法是一个抽象方法,需要在子类实现,onHandlerIntent方法执行后,stopSelt(int startId)就会停止服务,如果存在多个后台任务,执行完最后一个stopSelf(int startId)才会停止服务