AsyncTask研究

来源:互联网 发布:电线传输数据 编辑:程序博客网 时间:2024/05/16 18:21
 

 AsyncTask:

关于线程池:asyncTask对应的线程池ThreadPollExecutor都是进程范围内共享的,都是static的,所以asyncTask控制着进程范围内所有的子类的实例.由于这个限制的存在,当使用默认线程池的时候,如果线程数超过线程池的最大容量,线程池就会爆掉(3.0后默认串行执行,不会出现这个问题).针对这种情况,可以尝试自定义线程池,配合asyncTask使用..

 

关于默认线程池:核心线程池中最多有CPU_COUNT*2+1个,线程等待队列的最大等待数为128.但是可以自定义线程池.线程池是由AsyncTask来管理的,线程池允许tasks并行运行,需要注意的是并发情况下数据的一致性问题,新数据可能被来数据覆盖掉,类似volatile变量.所以如果希望tasks能够串行运行的话,使用SERIAL_EXECUTOR(同步线程池).

自定义线程池: executeOnExecutor(Executor exec ,Params…params) 自定义Executor execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);}

 

AsyncTask在不同sdk版本中的区别 :

  我们可以通过查看API得知,刚开始引入AsyncTask的时候,异步任务在一个线程中顺序的执行,也就是说每次我们可以执行的任务的数量是1个,不可以并行的执行任务.从API版本1.6的时候开始AsyncTask引入了线程池,支持同时执行5个异步任务.也就是说能同时执行5个异步任务,也就是说同时只可以有5个线程,超过线程的数量只可以等待了.等待前面的某一个线程执行完毕之后才可以继续调度执行.如果前面的线程执行的很慢,后面的只能是在等了.这就是AsyncTask的一个限制,而且这个限制在2.3之前是无法解决的.如果你的应用要需要大量的线程去执行任务的时候,只能放弃使用AsyncTask了,我们可以自己创建线程池来管理线程,或者是直接使用Thread.所以在2.3之前我们只能是分情况使用AsyncTask.

从3.0开始,做出了一些优化,每次启动一个线程执行一个任务,执行完成后再去执行第二个,也就是说每次只有一个后台的线程在执行我们提交的任务.

 

关于ASyncTask的生命周期:

 AsyncTask的生命不会随着activity的销毁而死亡,它会执行到DoInBackground()方法执行完毕.这个时候继续执行onPostExecute(Result result)方法,但是还可以我们调cancel方法.

我们销毁activity之前,要取消asyncTask,想一下我们如果没有取消asyncTask,这个可能让asyncTask直接崩溃,因为asyncTask执行完成之后会带回来数据,然后在处理结果的方法中,一般来更新界面,但是这个时候它要处理的view已经不存在了.所以我们使用asyncTask的时候要确保它正确的取消.(我们可以在activity销毁的destroy方法中调用asyncTask的cancel方法) 注意;可能我们正确的调用了cancel方法也未必可以取消任务,比如Doinbackground里面有一个操作,比如BitmapFactory.decodeStream(),那么这个操作会继续操作下去

 

关于asyncTask的内存泄漏

  asyncTask的修饰, 如果在activity内被声明为非静态的内部类,那么activity的一个引用会被asyncTask保留.如果activity已经被销毁,但是asyncTask继续在内存中保留着activity的一个引用,导致activity不能被回收,会引起内存泄漏.

 

结果丢失:

         屏幕旋转或者是activity在后台被杀死之后会导致activity重新创建,之前运行的asyncTask会保留对activity的一个引用,.这个引用已经是无效的,这个时候调用onPostExecute()再去更新界面将不会生效

1 0