AsyncTask

2016-12-07  本文已影响49人  学不好语文的LJ码农

以下内容整理自互联网,仅用于个人学习


1. 为什么使用AsyncTask

我们都知道,Android UI是线程不安全的,主要负责控制UI页面的显示、更新、交互等,一般情况,我们把耗时的操作(例如网络请求、数据库操作、复杂计算)放到单独的子线程中操作,以避免主线程的阻塞。如果想要在子线程里进行UI操作,就需要借助Android的异步消息处理机制。

但如果耗时的操作太多,那么我们需要开启太多的子线程,这就会给系统带来巨大的负担,随之也会带来性能方面的问题。在这种情况下我们就可以考虑使用类AsyncTask来异步执行任务,不需要子线程和Handler(内部还是通过子线程和Handler方式实现),就可以完成异步操作和刷新UI。

不要随意使用AsyncTask,除非你必须要与UI线程交互.默认情况下使用Thread即可,要注意需要将线程优先级调低。AsyncTask适合处理短时间的操作,长时间的操作,比如下载一个很大的视频,这就需要你使用自己的线程来下载。

2. AsyncTask的原理

AsyncTask封装了线程池和Handler,AsyncTask的内部Handler和ThreadPoolExecutor都是进程范围内共享的,其都是static的,也即属于类的。

AsyncTask内部会创建一个进程作用域的线程池来管理要运行的任务,也就就是说当你调用了AsyncTask的execute()方法后,AsyncTask会把任务交给线程池,由线程池来管理创建Thread和运行Therad。

AsyncTask主要作用:

  • 与主线程的交互

3. AsyncTask的基本用法

Android的AsyncTask比Handler更轻量级一些(只是代码上轻量一些,而实际上要比Handler更耗资源),适用于简单的异步处理。Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),因为UI的更新只能在主线程中完成,因此异步处理是不可避免的。

AsyncTask对线程间的通讯做了包装,使后台线程和UI线程可以简易通讯:后台线程执行异步任务,将result告知UI线程。

  1. 由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它。

在继承时我们可以为AsyncTask类指定三个泛型参数

  • Params: 输入参数,对应excute()方法中传递的参数。如果不需要传递参数,则直接设为void即可。

一个最简单的自定义AsyncTask就可以写成如下方式:

class DownloadTask extends AsyncTask<Void, Integer, Boolean> {  
   ……  
}  
  1. 重写AsyncTask中的几个方法

必须重写的方法:

  • doInBackground(Params…) :在子线程(其他方法都在主线程执行)中执行比较耗时的操作,不能更新UI,执行过程中可以调用publishProgress(Progress…)来更新任务的进度。Progress方法是AsycTask中一个final方法只能调用不能重写。

有必要时可以重写下面三个方法:

  • onProgressUpdate(Progress…):可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。

4. AsyncTask示例

public class MyTask extends AsyncTask<String, Integer, String> {   
    //执行的第一个方法用于在执行后台任务前做一些UI操作   
    @Override   
    protected void onPreExecute() {   
 
    }   
 
    //第二个执行方法,在onPreExecute()后执行,用于后台任务,不可在此方法内修改UI 
    @Override   
    protected String doInBackground(String... params) {   
         //处理耗时操作 
        return "后台任务执行完毕";   
    }   
 
   /*这个函数在doInBackground调用publishProgress(int i)时触发,虽然调用时只有一个参数   
    但是这里取到的是一个数组,所以要用progesss[0]来取值   
    第n个参数就用progress[n]来取值   */ 
    @Override   
    protected void onProgressUpdate(Integer... progresses) {   
        //"loading..." + progresses[0] + "%" 
        super.onProgressUpdate(progress);   
    }   
 
    /*doInBackground返回时触发,换句话说,就是doInBackground执行完后触发   
    这里的result就是上面doInBackground执行后的返回值,所以这里是"后台任务执行完毕"  */ 
    @Override   
    protected void onPostExecute(String result) {  
 
    }   
 
    //onCancelled方法用于在取消执行中的任务时更改UI   
    @Override   
    protected void onCancelled() {   
 
    }   
}

在主线程中做如下操作:

MyTask t= new MyTask(); 
t.execute();//这里没有参数

5. 使用AsyncTask的几条准则

上一篇 下一篇

猜你喜欢

热点阅读