Android -- 每日一问:在项目中使用AsyncTask会有什么问题吗?

Source

在这里插入图片描述

经典回答

那我们考查 AsyncTask 会问些什么呢?得先问问会不会用吧,看看知不知道有 onProgressUpdate 方法。

其次问一下是怎么理解 AsyncTask 的机制,有没有看过它的源代码?

这个问题主要看对方是否对 Android 的东西有好奇心,会主动去看 AsyncTask 的源码,或者能大体地讲清楚 AsyncTask 的原理。一般有好奇心的同学都比较善长学习,善长学习的人都能比较快融入团队。

AnsycTask 执行任务时,内部会创建一个进程作用域的线程池来管理要运行的任务,也就就是说当你调用了 AsyncTask.execute() 后,AsyncTask 会把任务交给线程池,由线程池来管理创建 Thread 和运行 Therad 。最后和 UI 打交道就交给 Handler 去处理了。

线程池可以同时执行多少个 TASK?

Android 3.0 之前(1.6之前的版本不再关注)规定线程池的核心线程数为5个(corePoolSize),线程池总大小为 128(maximumPoolSize),还有一个缓冲队列(sWorkQueue,缓冲队列可以放10个任务),当我们尝试去添加第139个任务时,程序就会崩溃。当线程池中的数量大于 corePoolSize,缓冲队列已满,并且线程池中的数量小于 maximumPoolSize,将会创建新的线程来处理被添加的任务。如下图会出现第16个Task比第6-15个Task先执行的情况。
image.png

多个AsyncTask任务是串行还是并行?

从Android 1.6到2.3(Gingerbread) AsyncTask是并行的,即上面我们提到的有5个核心线程的线程池(ThreadPoolExecutor)负责调度任务。从Android 3.0开始,Android团队又把AsyncTask改成了串行,默认的Executor被指定为SERIAL_EXECUTOR。

    /**
     * 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();

从它的说明也可以看出是串行的。如需要并行,可以通过设置executeOnExecutor(Executor)来实现多个AsyncTask并行。

    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
    
      

AsyncTask容易引发的Activity内存泄露

如果AsyncTask被声明为Activity的非静态的内部类,那么AsyncTask会保留一个对创建了AsyncTask的Activity的引用。如果Activity已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,导致Activity无法被回收,引起内存泄露。

当然,最后少不了问一句:“你在项目中,会用什么方案来替换AsyncTask呢?”

不过,学习它对理解Android的机制和线程池的使用还是很的意义的,所以强烈建议大家读一下它的源码

你的朋友是不是也在准备面试呢?你可以把今天的题目分享给好友,或许你可以帮到他。