多线程:给你一篇通俗易懂AsyncTask(使用&源码分析)+思维导图方式

在这里插入图片描述

AsyncTask了解

在这里插入图片描述

使用

        var task: MyAsynacTask? = null
         task = MyAsynacTask()
         task?.execute()// 开启任务
                // 只能执行一次&必须在UI线程调用
//                task?.execute()

        task?.cancel(true)// 手动取消
 

    var tag: String = "MyAsynacTask_"

    final inner class MyAsynacTask : AsyncTask<String, Int, String>() {
        override fun onPreExecute() {
            super.onPreExecute()
            Log.e(tag, "onPreExecute  下载之前")
            AsynacText.text = "下载之前"

        }

        override fun doInBackground(vararg params: String?): String {
            Log.e(tag, "doInBackground")
            var num: Int = 0
          
            while (num < 99) {
                num += 2
                publishProgress(num)
                Thread.sleep(30)
            }
            return ""
        }

        override fun onProgressUpdate(vararg values: Int?) {
            super.onProgressUpdate(*values)
            Log.e(tag, "onProgressUpdate  更新中")
            progressbar.setProgress(values[0]!!)
            AsynacText.text = "${values[0]!!} %"
        }

        override fun onPostExecute(result: String?) {
            super.onPostExecute(result)
            Log.e(tag, "onPostExecute  $result")
            AsynacText.text = "执行完毕"
        }

        override fun onCancelled() {
            super.onCancelled()
            Log.e(tag, "onCancelled")
            AsynacText.setText("已取消")
           progressbar.setProgress(0)
        }

        override fun onCancelled(result: String?) {
            super.onCancelled(result)
            Log.e(tag, "onCancelled  result:")
        }
    }


布局样式

两个btn & 一个ProgressBar & 一个Textview
在这里插入图片描述

注意事项:
  1. 只能执行一次
  2. 必须在UI线程调用

这里不在演示动图!
效果图:
1. 默认下载完毕:执行相关方法
在这里插入图片描述
2. 下载途中手动取消下载
在这里插入图片描述

源码分析

源码思维导图

在这里插入图片描述

核心颜色说明

以下是思维导图中的核心颜色区分:

  • 紫色
    必须重写 & 可重写的 & 手动调用 的核心方法,我们使用AsyncTask会用到这些回调方法
  • 红色
    源码中执行 的核心方法
  • 绿色
    手动调用execute,是如何添加到任务队列 的核心方法

具体分析

下面源码分析中,标题也会按照核心颜色去设置!

思维方向:

  1. 熟悉上图 AsyncTask了解 部分的概念、和必须重写 & 可重写 & 手动调用 的方法。最好先会怎么使用
  2. 看源码AsyncTask的构造方法做了哪些事情,可以先跟着看一遍,知道怎样的一个流程,熟悉这个流程中用到了哪些方法、哪些类(这里可以不用非要揪着某个函数死磕)
  3. 在从主动调用的方法execute()跟踪查看源码做了什么,即思维导图中的:主动调用
  4. 最后查看获取AsyncTask实例时,内部的默认初始化做了哪些操作。即思维导图中的:获取AsyncTask实例时的初始化配置
  5. 做完上面的操作,在去看任务是如何添加到线程池队列中的。即思维导图中的绿色代码
  6. 看完这些,再结合上图的思维导图,进行综合的理解。 或者跟着思维导图先熟悉也可。

注:我看源码时,边看边在笔记本上花草图,算是比较笨的方法吧

AsyncTask构造方法

在这里插入图片描述

public AsyncTask(@Nullable Looper callbackLooper) {
        mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()
            : new Handler(callbackLooper);
		
        mWorker = new WorkerRunnable<Params, Result>() {
            public Result call() throws Exception {
            	//1.  设置调用标识
                mTaskInvoked.set(true);
                Result result = null;
                try {
                    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                    //noinspection unchecked
                    // 2. 执行异步操作。即使用AsyncTask 必须重写的执行异步操作
                    result = doInBackground(mParams);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                // catch  设置取消标识
                    mCancelled.set(true);
                    throw tr;
                } finally {
                // 3. 获取Handler 对象,发送消息   分析->postResult
                    postResult(result);
                }
                return result;
            }
        };
        //用来包装Callable对象
        mFuture = new FutureTask<Result>(mWorker) {
            @Override
            protected void done() {
                try {
                // 复查任务的调用   分析->postResultIfNotInvoked
                    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);
                }
            }
        };
    }

  • 分析->postResult
    在这里插入图片描述
  private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }
  • 分析->postResultIfNotInvoked
 private void postResultIfNotInvoked(Result result) {
        final boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result); //分析->postResult
        }
    }
主动调用

在这里插入图片描述

 @MainThread
    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,Params... params) {
        // .... 省略N行代码
        // 1.设置Status为RUNNING状态
        mStatus = Status.RUNNING;
		//2. 任务开始之前回调该方法
        onPreExecute();
		// 3.赋值
        mWorker.mParams = params;
        // 4.将任务添加到线程池中   exec请看下面分析:获取AsyncTask实例时的初始化配置
        exec.execute(mFuture);

        return this;
    }
获取AsyncTask实例时的初始化配置

在这里插入图片描述

  • SerialExecutor

    private static class SerialExecutor implements Executor {
    // 1. 维护一个双向队列:ArrayDeque 没有容量限制,可根据需求自动进行扩容。
    //ArrayDeque不支持值为 null 的元素。
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

		//2.  exec.execute(mFuture);   调用时,将mFuture传入=添加一个新任务
		//synchronized同步锁,保证串行执行
        public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            // 3. mActive == null时调用 scheduleNext();去队列中取出1任务个执行
            if (mActive == null) {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() {
        //4. mActive = mTasks.poll() 取出队列头部任务
            if ((mActive = mTasks.poll()) != null) {
            //5. 执行即耗时任务   关于 THREAD_POOL_EXECUTOR请看下面   ThreadPoolExecutor:用于并行执行任务的线程池 分析
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }
  • ThreadPoolExecutor:用于并行执行任务的线程池

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors()
    //2.设置线程池的最大线程数为 CPU核数*2+1
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    //2.设置线程池的最大线程数为 CPU核数*2+1
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    // 3.线程池空闲线程存活时间30s
    private static final int KEEP_ALIVE_SECONDS = 30;
    //4. TimeUnit.SECONDS
    // 6.初始化线程工厂
    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());
        }
    };

//5.初始化存储任务的队列为LinkedBlockingQueue 最大容量为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;
    }

  • 初始化一个Handler(静态内部类:InternalHandler)
    在这里插入图片描述
总结

到这里分析完结。
本文主要是分模块去分析的,最后可以串联起来:具体看思维导图

  1. AsyncTask构造方法模块
  2. handler发送消息模块(postResult)
  3. 主动调用模块
  4. 获取AsyncTask实例时的初始化配置模块

上述:
1-2跟踪AsyncTask构造方法源码查看时,最终跟踪到Handler模块
3最后核心方法 *exec.execute(mFuture); 将mFuture传入=添加一个新任务
4最后会调用 THREAD_POOL_EXECUTOR.execute(mActive);执行耗时任务,即TAsyncTask构造方法中的new WorkerRunnable,重写的call方法中

感谢观看!如有什么不正确的,麻烦大佬指出。谢谢!

搞了将近两天,主要根据源码画思维导图这一块花的时间久点,大佬不妨点个赞吧。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值