美文网首页
AsyncTask源码分析

AsyncTask源码分析

作者: 风月寒 | 来源:发表于2020-10-07 14:39 被阅读0次
    AsyncTask的使用
    /**
     * 避免内存泄露,用弱引用包裹,加静态内部类的方式处理
      */
    //输入的参数 String  执行进度 Integer 返回的结果  String
    // a. Params:开始异步任务执行时传入的参数类型,对应excute()中传递的参数
    // b. Progress:异步任务执行过程中,返回下载进度值的类型
    // c. Result:异步任务执行完成后,返回的结果类型,与doInBackground()的返回值类型保持一致
    static class MyAsynTask extends AsyncTask<String,Integer,String>{
             
             private WeakReference<ProgressBar> progressBarWeakReference;
             private WeakReference<TextView> textViewWeakReference;
    
             public  MyAsynTask(ProgressBar progressBar,TextView textView){
                 progressBarWeakReference = new WeakReference<>(progressBar);
                 textViewWeakReference = new WeakReference<>(textView);
             }
    
    
            @Override
            protected void onPreExecute() {
                TextView textView = textViewWeakReference.get();
                textView.setText("加载中");
            }
    
            @Override
            protected String doInBackground(String... strings) {
                try {
                    int count = 0;
                    while (count <= 100){
                        Thread.sleep(1000);
                        count += 1;
                        publishProgress(count);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
                return null;
            }
    
            @Override
            protected void onProgressUpdate(Integer... values) {
                ProgressBar progressBar = progressBarWeakReference.get();
                progressBar.setProgress(values[0]);
                TextView textView = textViewWeakReference.get();
                textView.setText("Loading.."+ values[0] + "%");
            }
    
            @Override
            protected void onPostExecute(String s) {
                TextView textView = textViewWeakReference.get();
                textView.setText("加载完毕");
            }
    
            @Override
            protected void onCancelled() {
                TextView textView = textViewWeakReference.get();
                textView.setText("已取消");
                ProgressBar progressBar = progressBarWeakReference.get();
                progressBar.setProgress(0);
            }
        }
        
        /**
         * 在onDestroy的时候取消任务
         */
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            mMyAsynTask.cancel(true);
        }
    
    源码分析
    mMyAsynTask.execute();
    

    调用execute启动任务。

     @MainThread
        public final AsyncTask<Params, Progress, Result> execute(Params... params) {
            return executeOnExecutor(sDefaultExecutor, params);
        }
    

    从上面可以知道有一个@MainThread注解,表面该方法只能在主线程执行。

    @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.mParams = params;
            exec.execute(mFuture);
    
            return this;
        }
        
        @UnsupportedAppUsage
        private volatile Status mStatus = Status.PENDING;
        
        public enum Status {
            /**
             * Indicates that the task has not been executed yet.
             */
            PENDING,
            /**
             * Indicates that the task is running.
             */
            RUNNING,
            /**
             * Indicates that {@link AsyncTask#onPostExecute} has finished.
             */
            FINISHED,
        }
    

    首先判断状态,总共有三种状态,分别为PENDING,RUNNING,FINISHED。默认的为PENDING,当执行executeOnExecutor方法时,将状态改为RUNNING。

    这也是一个==AsyncTask对象不能被多次执行的原因。== 因为执行executeOnExecutor()时,只要初始状态不是PENDING就会报错。

    最后执行exec.execute(mFuture)。其中exec是sDefaultExecutor,下面来看一下sDefaultExecutor。

    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);
                }
            }
        }
    

    SerialExecutor 内部维持了一个队列,通过锁使得该队列保证AsyncTask中的任务是串行执行的,即多个任务需要一个个加到该队列中。加入的这个任务就是mFuture。

    exec.execute(mFuture)实际上是先向ArrayDeque这个队列中加入mFuture这个任务。然后调用scheduleNext(),调用THREAD_POOL_EXECUTOR执行队列头部的任务。

    mFuture = new FutureTask<Result>(mWorker)
    

    在加入时会执行r.run(),即执行mFuture.run().

    public void run() {
            if (state != NEW ||
                !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
                return;
            try {
                Callable<V> c = callable;
                if (c != null && state == NEW) {
                    V result;
                    boolean ran;
                    try {
                        result = c.call();//1
                        ran = true;
                    } catch (Throwable ex) {
                        result = null;
                        ran = false;
                        setException(ex);
                    }
                    if (ran)
                        set(result);
                }
            } finally {
                // runner must be non-null until state is settled to
                // prevent concurrent calls to run()
                runner = null;
                // state must be re-read after nulling runner to prevent
                // leaked interrupts
                int s = state;
                if (s >= INTERRUPTING)
                    handlePossibleCancellationInterrupt(s);
            }
        }
        
        //构造函数
        public FutureTask(Callable<V> callable) {
            if (callable == null)
                throw new NullPointerException();
            this.callable = callable;
            this.state = NEW;       // ensure visibility of callable
        }
    

    由构造函数我们可以知道,传入的callable就是mWorker。

    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(result);
                    }
                    return result;
                }
            };
    

    在mFuture.run()的run()方法中,会执行//1处,即执行mWorker.call()。在call方法中,先执行完doInBackground()方法,又执行postResult()方法。

    THREAD_POOL_EXECUTOR实际是个线程池,开启了一定数量的核心线程和工作线程。然后调用线程池的execute()方法。执行具体的耗时任务,即开头构造函数中mWorker中call()方法的内容。由此可知,真正执行耗时任务的是THREAD_POOL_EXECUTOR。SerialExecutor只是将任务加入其中。

    private Result postResult(Result result) {
            @SuppressWarnings("unchecked")
            Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                    new AsyncTaskResult<Result>(this, result));
            message.sendToTarget();
            return result;
        }
    

    然后通过Handler将耗时操作返回的结果放到主线程。

    private static Handler getMainHandler() {
            synchronized (AsyncTask.class) {
                if (sHandler == null) {
                    sHandler = new InternalHandler(Looper.getMainLooper());
                }
                return sHandler;
            }
        }
    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:
                        // There is only one result
                        result.mTask.finish(result.mData[0]);
                        break;
                    case MESSAGE_POST_PROGRESS:
                        result.mTask.onProgressUpdate(result.mData);
                        break;
                }
            }
        }   
        
    mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
                ? getMainHandler()
                : new Handler(callbackLooper);
                
    
    private Handler getHandler() {
        return mHandler;
    }
    

    这里使用sHandler对象发出了一条消息,消息中携带了MESSAGE_POST_RESULT常量和一个表示任务执行结果的AsyncTaskResult对象。这里对消息的类型进行了判断,如果这是一条MESSAGE_POST_RESULT消息,就会去执行finish()方法,如果这是一条MESSAGE_POST_PROGRESS消息,就会去执行onProgressUpdate()方法。

    private void finish(Result result) {
            if (isCancelled()) {
                onCancelled(result);
            } else {
                onPostExecute(result);
            }
            mStatus = Status.FINISHED;
        }
    

    可以看到,如果当前任务被取消掉了,就会调用onCancelled()方法,如果没有被取消,则调用onPostExecute()方法,这样当前任务的执行就全部结束了。

    然后将状态变成FINISHED。

    在3.0以前,最大支持128个线程的并发,10个任务的等待,同时执行138个任务是没有问题的;而超过138会马上出现java.util.concurrent.RejectedExecutionException。在3.0以后,无论有多少任务,都会在其内部单线程执行;

    如果想让AsyncTask在3.0以上的系统中并行: 调用AsyncTask的executeOnExecutor方法而不是execute方法

    btn_a.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    new MyTask("AsyncTask#1").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
                    new MyTask("AsyncTask#2").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
                    new MyTask("AsyncTask#3").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
                    new MyTask("AsyncTask#4").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
                    new MyTask("AsyncTask#5").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");
                }
            });
            
    2020-10-07 14:32:59.341 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#2execute finish at 2020-10-07 14:32:59
    2020-10-07 14:32:59.342 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#1execute finish at 2020-10-07 14:32:59
    2020-10-07 14:32:59.343 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#4execute finish at 2020-10-07 14:32:59
    2020-10-07 14:32:59.343 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#3execute finish at 2020-10-07 14:32:59
    2020-10-07 14:32:59.343 29216-29216/com.example.asyntask E/AsyncTask: AsyncTask#5execute finish at 2020-10-07 14:32:59
    

    相关文章

      网友评论

          本文标题:AsyncTask源码分析

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