AsyncTask - 基础篇

作者: CokeNello | 来源:发表于2019-03-16 13:22 被阅读0次

    概述

    AsyncTask,Android早期推介处理异步任务的类,虽然现在有很多种方式去处理异步任务,如RX,三方库等等,但还是建议大家了解一下这个基础的原生类,毕竟熟悉源码,扎实自己的基础和对面试也有很大帮助。

    AsyncTask是一个轻量级选手,适合处理轻量级的后台任务。处理过程中还可以把处理的进度反馈到主线程中,方便我们更新UI,不需要我们去操作 handler,在早期 Android 版本中是十分方便的工具。

    1. 了解 AsyncTask 的泛型

    使用 AsyncTask 我们需要继承:
    public abstract class AsyncTask<Params, Progress, Result>
    其需要我们定义三个参数泛型:

    • Params,输入参数,执行任务时发送到后台任务的参数类型
    • Progress,后台任务执行时,更新进度的参数类型
    • Result,后台任务执行完毕的输出结果

    2. 实现 doInBackground

    继承后我们需要实现 doInBackground 这个方法,顾名思义,其跑在子线程,在里面我们可以肆无忌惮地进行耗时的操作:

    private static class MyAsyncTask extends AsyncTask<String,Integer,Boolean> {
        @Override
        protected Boolean doInBackground(String... strings) {
            //do some thing
            return true;
        }
    }
    

    doInBackground 是核心,其传入参数类型,就是我们继承时候定义的三个泛型中的:Params,其最后return的类型就是我们定义的泛型 Result。doInBackground 跑在子线程中,那我们怎么更新进度呢?怎么更新UI呢?在哪里更新呢?

    3. 任务执行进度更新

    如果我们需要在 doInBackgroud 的耗时操作中,及时地回调执行任务的进度,我们可以直接调用方法 pulishProgress 来进行,pulishProgress 需要传入一个参数,这个参数就是我们一开始定义的泛型:progress:

        /**
         * 后台任务处理方法,运行在
         * 子线程,可以做一些耗时任务
         * @param strings 输入参数,对应于泛型:Params
         * @return 结果
         */
        @Override
        protected Boolean doInBackground(String... strings) {
            Log.i(TAG,"doInBackground...");
            int i=0;
            while(i<100){
                if (isCancelled())
                    break;
                i++;
                //任务执行过程进度/参数的回调,对应于泛型:Progress
                publishProgress(i);
                try {
                    Thread.sleep(200);
                } catch (InterruptedException ignored) {
                }
            }
            //返回值代表最后的结果,对应于泛型:Result
            return true;
        }
    

    通过 publishProgress 更新的进度值,最后会回调到方法 onProgressUpdate 中,我们重写这个方法,在里面做UI更新:

        /**
         * 任务执行过程中的更新,
         * 由子方法:publishProgress()
         * 触发,运行在UI线程中
         * @param values 参数
         */
        @Override
        protected void onProgressUpdate(Integer... values) {
            TextView tvProgress = textViewWeakReference.get();
            ProgressBar progressBar = progressBarWeakReference.get();
            if (tvProgress!=null)
                tvProgress.setText(values[0]+"%");
            if (progressBar!=null)
                progressBar.setProgress(values[0]);
        }
    

    4. 任务的开启和取消

    • 任务开启:
    myAsyncTask = new MyAsyncTask(TestAsyncTaskActivity.this,progressBar,tvProgress);
    myAsyncTask.execute("start");
    
    • 任务取消,这里需要传入一个参数:如果传入的是false并且 doInBackgroud 已经开始执行,当前任务是不会被终止的,而是会继续执行直到异常或者执行完毕,如果未开始,是可以被终止的。如果传入的是true,会调用当前线程的interrupt()方法,把中断标志位设为true,最终会调用到,FutureTask 里面的 cancel 方法,可这样真的会被终止吗?可不一定,可以看看这篇文章:FutureTask介绍及使用
    if (myAsyncTask!=null)
        myAsyncTask.cancel(true);
    

    5. 其他重要的方法

    • protected void onPreExecute()
      任务执行开启之前回调,即在doInBackgroud 方法前被调用
      ,运行在UI线程,可以在这里做一些参数的初始化

    • protected void onPostExecute(Boolean bool)
      任务执行结束的回调,运行在UI线程,入参就是在继承类的时候,定义的泛型 Result。

    • protected void onCancelled()
      执行 task.cancel() 方法后,onPostExecute 这个方法不会被回调,取而代之,被回调的是 onCancelled 方法,其运行在UI线程。

    6. 总结

    本篇主要的目的是让大家了解到 AsyncTask 的基础用法,主要是要掌握其三个泛型的作用,以及泛型对应到哪个方法里面,还有最重要的是,清楚掌握每个方法回调的线程和其作用,还有 AsyncTask 任务从开始到结束的生命周期:

    image.png

    看起来 AsyncTask 好像还挺好用的,但其实有很多坑,我们下一篇再说。


    喜欢分享吗?欢迎投稿 ~ 有稿费呢

    技术酱

    相关文章

      网友评论

        本文标题:AsyncTask - 基础篇

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