今天看啥  ›  专栏  ›  CokeNello

AsyncTask - 基础篇

CokeNello  · 掘金  ·  · 2020-03-28 14:28
阅读 11

AsyncTask - 基础篇

概述

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 好像还挺好用的,但其实有很多坑,我们下一篇再说。


技术酱专注 Android 技术,工作日不定时推送新鲜文章,如果你有好的文章想和大家分享(有稿费哦),欢迎关注投稿!

技术酱




原文地址:访问原文地址
快照地址: 访问文章快照