AsyncTask源码解析

AsyncTask异步任务,方便我们在Android在子线程执行任务,在主线程执行结果,避免ANR。

  1. AsyncTask基本使用:
public class MainActivity extends AppCompatActivity {

    final private static String TAG = "AsyncTask_Test";

    private TextView show;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        show = (TextView) findViewById(R.id.show);
    }

    public void download(View view) {
        DownloadTask task = new DownloadTask(this);
        try {
            task.execute(new URL("http://www.jianshu.com/"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private class DownloadTask extends AsyncTask {

        ProgressDialog progressDialog;
        int hasRead = 0;
        Context context;

        DownloadTask(Context context) {
            this.context = context;
        }

        @Override
        protected String doInBackground(URL... params) {
            StringBuilder stringBuilder = new StringBuilder();
            try {
                URLConnection connection = params[0].openConnection();
                BufferedReader bufferedReader = new BufferedReader(
                        new InputStreamReader(connection.getInputStream(), "utf-8"));
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    stringBuilder.append(line).append("\n");
                    hasRead++;
                    publishProgress(hasRead);
                }

                return stringBuilder.toString();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String s) {
            show.setText(s);
            progressDialog.dismiss();
            super.onPostExecute(s);
        }

        @Override
        protected void onPreExecute() {
            progressDialog = new ProgressDialog(context);
            progressDialog.setTitle("Downloading");
            progressDialog.setMessage("Please wait ...");
            progressDialog.setCancelable(false);
            progressDialog.setMax(202);
            progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            progressDialog.setIndeterminate(false);
            progressDialog.show();

            super.onPreExecute();
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            show.setText("Has read " + values[0] + " lines.");
            progressDialog.setProgress(values[0]);

            super.onProgressUpdate(values);
        }
    }
}
  1. AsyncTask源码分析
    我们分析AsyncTask主要分为三步:
  • static属性
  • 构造函数
  • execute方法
    2.1 static属性:
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;
    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());
        }
    };
    //线程池的任务队列,任务个数不能超过128,否则会抛出异常,拒绝任务。
    private static final BlockingQueue sPoolWorkQueue =
            new LinkedBlockingQueue(128);
    //----------------------------以上属性为线程池的参数---------------------------
    
    public static final Executor THREAD_POOL_EXECUTOR;

    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        //允许核心线程销毁
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }
    //----------------------------线程池初始化---------------------------
    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
    private static class SerialExecutor implements Executor {
        //任务队列(集成了队列和栈的双重特性)这里使用的是队列
        final ArrayDeque mTasks = new ArrayDeque();
        //活动任务
        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);
            }
        }
    }
    //----------------------------执行器初始化---------------------------

2.2 构造函数:

    /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     * 创建一个新的异步任务,构造函数必须在UI线程中被调用。
     */
    public AsyncTask() {
        this((Looper) null);
    }

    /**
     * 这个构造函数对我们是隐藏的,不允许被调用
     * @hide
     */
    public AsyncTask(@Nullable Handler handler) {
        this(handler != null ? handler.getLooper() : null);
    }

    /**
     * 这个构造函数对我们是隐藏的,不允许被调用
     * @hide
     */
    public AsyncTask(@Nullable Looper callbackLooper) {
        //我们能用的构造函数只有一个空构造,所以mHandler=UI线程的Handler
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()
            : new Handler(callbackLooper);
        //创建一个工作任务。
        mWorker = new WorkerRunnable() {
            public Result call() throws Exception {
                mTaskInvoked.set(true);
                Result result = null;
                try {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    //noinspection unchecked
                    result = doInBackground(mParams);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    mCancelled.set(true);
                    throw tr;
                } finally {
                    //任务执行结束后执行postResult方法。
                    postResult(result);
                }
                //任务执行结束返回执行结果。
                return result;
            }
        };
        //创建一个future任务,保存工作任务。
        mFuture = new FutureTask(mWorker) {
            @Override
            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);
                }
            }
        };
    }

2.3 execute方法。

    /**
      * MainThread标记只能在祝线程调用。
      **/
    @MainThread
    public final AsyncTask execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }

    @MainThread
    public final AsyncTask executeOnExecutor(Executor exec,
            Params... params) {
        //判断运行状态是否是PENDING,如果不是抛出异常终止运行,所以一个异步任务对象只能运行一次。
        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方法。
        onPreExecute();
        //给工作任务的mParams赋值
        mWorker.mParams = params;
        //执行器执行任务,此时跳转到sDefaultExecutor的execute方法中执行,并将future任务传过去,执行mFuture的run方法。
        exec.execute(mFuture);

        return this;
    }
    /**
      * mFuture的run方法。run方法执行工作任务的call方法,call方法执行doInBackground方法。(此时执行的任务在子线程中执行。)
      **/
    public void run() {
        if (state != NEW ||
            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
            return;
        try {
            //callable就是工作任务(mWorker)。
            Callable c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    //调用工作任务的call方法,获取执行结果。call方法中执行了doInBackgroud方法,并返回了执行结果。
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    //发生异常后执行的方法。
                    setException(ex);
                }
                if (ran)
                    //顺利执行完成后,执行的方法。
                    set(result);
            }
        } finally {
            runner = null;
            int s = state;
            if (s >= INTERRUPTING)
                //调用了cancle方法(手动中断线程)或线程被中断执行此方法。
                handlePossibleCancellationInterrupt(s);
        }
    }
    /**************************************************************************
    此时执行结果分为三个分支:
    - 顺利执行完成
    - 执行时代码发生异常
    - 执行时线程被中断
    **************************************************************************/
    //我们先看前两种情况:顺利执行完成、执行时代码发生异常
    protected void set(V v) {
        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
            outcome = v;
            //更改state状态变量为NORMAL(2)
            U.putOrderedInt(this, STATE, NORMAL); // final state
            //调用finishCompletion方法
            finishCompletion();
        }
    }

    protected void setException(Throwable t) {
        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
            outcome = t;
            //更改state状态变量为EXCEPTIONAL(3)
            U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
            //调用finishCompletion方法
            finishCompletion();
        }
    }
    //可以看到,顺利执行完成、执行时代码发生异常,都调用了finishCompletion方法,只是状态值不一样。
    //finishCompletion调用了构造函数中mFuture的done方法
    private void finishCompletion() {
        // assert state > COMPLETING;
        for (WaitNode q; (q = waiters) != null;) {
            if (U.compareAndSwapObject(this, WAITERS, q, null)) {
                for (;;) {
                    Thread t = q.thread;
                    if (t != null) {
                        q.thread = null;
                        LockSupport.unpark(t);
                    }
                    WaitNode next = q.next;
                    if (next == null)
                        break;
                    q.next = null; // unlink to help gc
                    q = next;
                }
                break;
            }
        }
        //调用构造函数中mFuture的done方法。
        done();
        //mFuture中的工作任务置为空
        callable = null;        // to reduce footprint
    }

    //mFuture中的done方法在构造函数中(已经贴过了在这就不贴了)done方法调用了postResultIfNotInvoked方法
    private void postResultIfNotInvoked(Result result) {
        final boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

    private Result postResult(Result result) {
        //通过handler发送消息到主线程,并将结果带过去。
        //AsyncTaskResult封装了执行结果和AsyncTask对象。
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult(this, result));
        message.sendToTarget();
        return result;
    }

private static class InternalHandler extends Handler {
        public InternalHandler(Looper looper) {
            super(looper);
        }

        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult result = (AsyncTaskResult) msg.obj;
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    // 调用AsyncTask中的finish方法。
                    result.mTask.finish(result.mData[0]);
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);
                    break;
            }
        }
    }
    //finish中执行onCancelled,onPostExecute方法。
    private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }

2.4 AsyncTask更新进度条源码解析:
AsyncTask更新进度条需要手动调用publishProgress方法,publishProgress方法发送消息到handler执行AsyncTask对象中的onProgressUpdate方法。

    //标记在工作(子)线程中调用
    @WorkerThread
    protected final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult(this, values)).sendToTarget();
        }
    }

总结:

  1. new AysncTask 和 execute方法,只能在UI线程执行。
  2. publishProgress只能在工作线程中执行。
  3. AsyncTask执行器默认是SerialExecutor也就是一个任务一个任务执行,不管线程池中有多少个线程,同时执行的只有一个线程。
    建议:AsyncTask中只执行耗时比较少的异步操纵,不要同时执行过多的任务。

注意:

  1. Activity或者Fragment中不要不要定义非静态的内部类AsyncTask,AsyncTask内部类会持有外部类的隐式引用。由于AsyncTask的生命周期可能比Activity的长,当Activity进行销毁AsyncTask还在执行时,由于AsyncTask持有Activity的引用,导致Activity对象无法回收,进而产生内存泄露。
  2. Activity重新创建时AsyncTask数据丢失。当Activity销毁并创新创建后,还在运行的AsyncTask会持有一个Activity的非法引用即之前的Activity实例。导致onPostExecute()没有任何作用。

你可能感兴趣的:(AsyncTask源码解析)