码迷,mamicode.com
首页 > 其他好文 > 详细

AsyncTask原理

时间:2016-05-15 19:46:22      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:

1、对于耗时的操作(如上传下载、读写数据库等),为了不阻塞主线程,我们的一般方法是开启“子线程”。如果需要更新UI,则需要使用handler

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

3、AsyncTask:对线程间的通讯做了轻量级的包装,代码上较之handler更为轻量(实际更耗资源),使用它后台线程和UI线程可以简易通讯:后台线程执行异步任务,将result告知UI线程。

      AsyncTask本质上是一个静态的线程池,由它派生出来的子类可以实现不同的异步任务,但这些任务都是提交到该静态线程池中执行,执行的时候通过调用doInBackground()方法执行异步任务,期间会通过Handler将相关的信息发送到UI线程中,但神奇的是,并不是调用UI线程中的回调方法,而是AsyncTask本身就有一个Handler的子类InternalHandler会响应这些消息并调用AsyncTask中相应的回调方法。从上面的代码中我们也可以看到,UI的ProgressBar的更新是在AsyncTask的onProgressUpdate(),而ImageView是在onPostExecute()方法里。这是因为InternalHandler其实是在UI线程里面创建的,所以它能够调用相应的回调方法来更新UI。

      AsyncTask就是专门用来处理后台任务的,而且它针对后台任务的五种状态提供了五个相应的回调接口,使得我们处理后台任务变得非常方便。

      如果只是普通的UI更新操作,像是不断更新TextView这种动态的操作,可以使用Handler,但如果是涉及到后台操作,像是下载任务,然后根据后台任务的进展来更新UI,就得使用AsyncTask,但如果前者我们就使用AsyncTask,那真的是太大材小用了!!

4、两组成部分

一个是与主线各的交互,另一个就是线程的管理调度。虽然可能多个AsyncTask的子类的实例,但是AsyncTask的内部Handler和ThreadPoolExecutor都是进程范围内共享的,其都是static的,也即属于类的,类的属性的作用范围是CLASSPATH,因为一个进程一个VM,所以是AsyncTask控制着进程范围内所有的子类实例。

5、使用方法

自定义AsyncTask,在耗时的地方调用自定义的AsyncTask。可以参照以下代码示例。

step1:继承AsyncTask<Params,Progress,Result>

           Params:输入参数。对应的是调用自定义的AsyncTask的类中调用excute()方法中传递的参数。如果不需要传递参数,则直接设为Void即可。

           Progress:子线程执行的百分比

           Result:返回值类型。和doInBackground()方法的返回值类型保持一致。

step2:实现以下几个方法:执行时机和作用看示例代码,以下对返回值类型和参数进行说明

          onPreExecute():无返回值类型。不传参数

          doInBackground(Params... params):返回值类型和Result保持一致。参数:若无就传递Void;若有,就可用Params

          publishProgress(Params... params):在执行此方法的时候会直接调用onProgressUpdate(Params... values)

          onProgressUpdate(Params... values):无返回值类型。参数:若无就传递Void;若有,就可用Progress

          onPostExecute(Result  result) :无返回值类型。参数:和Result保持一致。

step3:在调用自定义的AsyncTask类中生成对象;

          执行  :对象.excute(Params... params);

6、基本使用

    protected void onPreExecute()

    protected abstract Result doInBackground(Params... params)

    protected void onPostExecute(Result result)

    protected void onProgressUpdate(Progress... values)

7、源码分析

    private static final int CORE_POOL_SIZE = 5;        //核心线程数

    private static final int MAXIMUM_POOL_SIZE = 128;   //最大线程数

    private static final int KEEP_ALIVE = 1;            //超时时间,当线程数超过核心线程数时,超过这个时间的空线程就会被销毁,直到线程数等于核心线程    

8、缺陷

  1. 同时只有5个线程去访问网络-->这个是重点
  2. 线程数目超过128,会抛异常RejectedExecutionException-->这个情况其实还好;

    解决方法:由一个控制线程来处理AsyncTask的调用判断线程池是否满了,如果满了则线程睡眠否则请求AsyncTask继续处理。

9、版本差异(线程的管理调度方面)

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

  1. CORE_POOL_SIZE MAXIMUM_POOL_SIZE KEEP_ALIVE在不同的版本上.值是不一样;
  2. 1.5前是串行执行的.每次执行1个任务
  3. 1.6-2.3(API4-10)的版本.是并行执行的.每次执行5个任务
  4. 3.0后提供串行和并行,默认情况是串行

           executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, null);//串行

           executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null);//并行

10、简单封装

> 实际开发我们会去继承Asynctask

11、与handler相比

11.1 AsyncTask

  优点:简单快捷,过程可控、易于维护;

  缺点:在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来;核心线程数只有5个

11.2 handler

  优点:结构清晰,功能定义明确;对于多个后台任务时,简单,清晰

  缺点:在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)

11.3 AsyncTask是对Thread+Handler良好的封装,在android.os.AsyncTask代码里仍然可以看到Thread和Handler的踪迹

11.4 AsyncTask底层是一个线程池,而handler底层是一个消息队列(不开启线程),所以AsyncTask虽然有着更为轻量级的代码,但较之handler更耗资源

11.5 归纳起来,AsyncTask、handler的不同在于:量级、编写难易程度、资源消耗、底层,以及应用场景等

12、小结

    12.1 Task的实例必须在UI thread中创建

    12.2 execute方法必须在UI thread中调用

    12.3 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground=\‘#\‘" onProgressUpdate(Progress...)这几个方法

    12.4 该task只能被执行一次,否则多次调用时将会出现异常 

    12.5 数据简单使用AsyncTask:实现代码简单;

            数据量多且复杂使用handler+thread:相比较AsyncTask来说能更好的利用系统资源且高效

http://www.cnblogs.com/suinuaner/archive/2013/04/11/android_fifty.html

http://www.cnblogs.com/wenjiang/p/3180324.html

http://blog.csdn.net/hitlion2008/article/details/7983449

AsyncTask原理

标签:

原文地址:http://www.cnblogs.com/nathan909/p/5328082.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!