Android-AsyncTask源码解析

AsyncTask 使用

    public void test(){
        MyAsyncTask myAsyncTask = new MyAsyncTask();
        myAsyncTask.execute("");
    }
    class  MyAsyncTask extends AsyncTask<String, Integer, Boolean>{

        @Override
        protected Boolean doInBackground(String... strings) {
            //zi线程操作
            return true;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            //ui 线程
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            //ui 线程上操作
        }
    }

使用很简单,创建一个类继承AsyncTask

  • 重写doInBackground方法在该方法里做耗时操作
  • 重写onPostExecute在耗时操作结束后这里会回调到主线程做结果处理操作

myAsyncTask.execute调用AsyncTask

源码解析

构造函数

 public AsyncTask(@Nullable Looper callbackLooper) {
    /**
     * 初始化mHandler
     */
    mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()
            : new Handler(callbackLooper);
    /**
     * 初始化WorkerRunnable
     */
    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
        	//设置标识让postResultIfNotInvoked方法里不会重复执行
            mTaskInvoked.set(true);
            Result result = null;
            try {
                //线程优先级设置后台线程
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //执行doInBackground返回result
                result = doInBackground(mParams);
                Binder.flushPendingCommands();
            } catch (Throwable tr) {
                //异常则取消
                mCancelled.set(true);
                throw tr;
            } finally {
                //调用postResult方法
                postResult(result);
            }
            return result;
        }
    };
    /**
     * 初始化FutureTask
     */
    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);
            }
        }
    };
}

可以看到构造函数里主要做了三件事

  • 初始化 mHandler,这里会判断是否传入了Looper如果没有会获取主线程的Looper

所以不传Looper时不能在子线程里初始化AsyncTask

  • 初始化WorkerRunnable,在mWorker里的call方法实现了doInBackgroundpostResult(通过handler调用postResult方法)
  • 初始化FutureTask

executeOnExecutor 方法

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

当我们调用execute方法时,他会最终调用到executeOnExecutor方法,并传入一个sDefaultExecutor线程池(下面讲到)
executeOnExecutor方法里会判断这个任务是否已经执行过,如果正在执行中或者已经执行完成则会抛出一个IllegalStateException异常,如果没有执行过则开始执行onPreExecute方法,然后向线程池里抛mFuture任务执行耗时操作

所以AsyncTaskexecute方法只能调用一次

两个线程池

AsyncTask有两个线程池,一个用来执行具体任务,另一个只用作任务排对

    //第一个线程池,用作执行具体任务
    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;
    }
 
    /**
     * An {@link Executor} that executes tasks one at a time in serial
     * order.  This serialization is global to a particular process.
     */
    //第二个线程池,用作阻塞队列,进行任务的存储
    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
 
    private static final int MESSAGE_POST_RESULT = 0x1;
    private static final int MESSAGE_POST_PROGRESS = 0x2;
    //上述说道
    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

可以看到sDefaultExecutor实则就是SerialExecutor实例,SerialExecutor由一个数组结构的双向队列构成,从队列中取出任务后放入THREAD_POOL_EXECUTOR执行;在execute方法里可以看到这个线程是个串行任务队列线程池目的就是为了做到排队作用一次只能有一个任务执行。

所以AsyncTask的任务是串行的(API3.0以后,3.0之前是并行)

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

内存泄漏

  • 在Activity中使用AsyncTask,AsyncTask持有Activity的引用,如果在网络请求没有结束,但是Activity已经被关闭的情况下,Actuvity的引用的不到释放,就会造成内存泄漏。(解决方法使用弱引用、判断activity等)
  • 为什么cancel方法不能解决内存泄漏
    public final boolean cancel(boolean mayInterruptIfRunning) {
        mCancelled.set(true);
        return mFuture.cancel(mayInterruptIfRunning);
    }
   public boolean cancel(boolean mayInterruptIfRunning) {
       if (!(state == NEW &&
             U.compareAndSwapInt(this, STATE, NEW,
                 mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
           return false;
       try {    // in case call to interrupt throws exception
           if (mayInterruptIfRunning) {
               try {
                   Thread t = runner;
                   if (t != null)
                       t.interrupt();
               } finally { // final state
                   U.putOrderedInt(this, STATE, INTERRUPTED);
               }
           }
       } finally {
           finishCompletion();
       }
       return true;
   }

可以看到cancel方法最终不过是调用了FutureTaskcancel方法,该方法里只是调用了线程的interrupt方法,而interrupt方法不会立马中断一个正在运行的线程,而是发出中断请求然后由线程在一个合适的时刻中断自己。所以他并不能立马中断操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值