美文网首页
AsyncTask源码解析

AsyncTask源码解析

作者: LinuxPara | 来源:发表于2017-11-23 17:00 被阅读17次

    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<URL, Integer, String> {
    
            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<Runnable> sPoolWorkQueue =
                new LinkedBlockingQueue<Runnable>(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<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);
                }
            }
        }
        //----------------------------执行器初始化---------------------------
    

    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<Params, Result>() {
                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<Result>(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<Params, Progress, Result> execute(Params... params) {
            return executeOnExecutor(sDefaultExecutor, params);
        }
    
        @MainThread
        public final AsyncTask<Params, Progress, Result> 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<V> 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<Result>(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<Progress>(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源码解析

          本文链接:https://www.haomeiwen.com/subject/extzvxtx.html