asyncTask详解

介绍

android UI是线程不安全的,所以想实如今子线程中刷新UI就须要借助一些机制来实现,通常有两种方法:handler+message;还有一种就是今天咱们要讲的asyncTask。asyncTask相对handler+message要轻量级一些。java

基本用法

asyncTask是一个抽象类,所以咱们须要自定义一个类来继承他,而且实现他的方法。android

asyncTask指定了三个泛型参数,其中Params是可变长的泛型参数,三个参数用法以下:web

Params:asyncTask传入的参数可在后台执行任务时使用数据库

Progress:后台执行任务时,若是须要在前台显示进度,这里是指定泛型做为进度单位缓存

Result:后台执行任务完成,若是须要返回结果到前台,这里是指定泛型做为返回值类型安全

除了参数下面介绍下咱们常常须要重写的四个方法:多线程

onPreExecute():在任务执行以前调用,进行一些初始化操做,好比显示一个进度条,这个方法是在主线程运行的。并发

doInBackground(Void... arg0):这个方法是用来执行耗时操做的,把你想要异步处理的任务的代码放在这里面,这个确定是在子线程执行的。因此这个方法里面不能进行UI操做,若是想要更新UI的话,好比更新进度能够调用publishProgress(values)方法。异步

onProgressUpdate(Integer... values):后台执行了publishProgress(values);方法后处过来的值就能够用来更新前台的进度了,可见这个是在主线程执行的。async

onPostExecute(Boolean result):后台任务执行完毕返回结果的时候会调用这个方法,将结果返回给主进程或者进行UI操做,可见也是在主进程进行的。

还有一个onCancelled()方法,当用户取消任务的时候调用。有两点须要注意的地方:

一、asyncTask的实例化操做和execute()方法调用必须在UI线程操做。

二、asyncTask只能被执行一次,不能重复执行。源码里有一个判断:若是任务正在运行或者是已经结束的任务重复调用会抛出异常。

下面咱们来自定义一个asyncTask

public class MyAsyncTask extends AsyncTask<Void, Integer, Boolean>{
 @Override
 protected void onPreExecute() {
  // TODO Auto-generated method stub
  super.onPreExecute();
 }
 @Override
 protected Boolean doInBackground(Void... arg0) {
  // TODO Auto-generated method stub
  publishProgress(values);
  return null;
 }
 @Override
 protected void onProgressUpdate(Integer... values) {
  // TODO Auto-generated method stub
  super.onProgressUpdate(values);
 }
 @Override
 protected void onPostExecute(Boolean result) {
  // TODO Auto-generated method stub
  super.onPostExecute(result);
 }
 @Override
 protected void onCancelled() {
  // TODO Auto-generated method stub
  super.onCancelled();
 }
}

这里咱们把AsyncTask的第一个泛型参数指定为Void,表示在执行AsyncTask的时候不须要传入参数给后台任务,第二个泛型参数指定为Integer,表示使用整型数据来做为进度显示单位。第三个泛型参数指定为Boolean,表示子线程中返回的数据类型。

Android 3.0之前AsyncTask容许同时执行5个任务,线程池大小为128个,也就是说添加了10个任务,只有前五个在执行,等有一个执行完毕才会执行第六个,固然最多添加128个任务;3.0以后改为了只容许同时执行一个任务,为何变少了呢?3.0之后增长了他的灵活性,AsyncTask能够接受自定义线程池了。

public ExecutorService executorService = Executors.newFixedThreadPool(5);  
new MyAsyncTask().executeOnExecutor(executorService);

以上代码自定义了一个线程数为5的线程池,一样是能够执行5个任务。

 线程池

说道线程池,之前还真没接触过,只是用用别人封装好了的罢了。正好遇到了,也就了解一下,毕竟技不压身,哈哈哈...

先来看下ExecutorService,ExecutorService是线程池的一个服务,能够随时关闭线程池,它里面有几个经常使用的线程池对象:

newCachedThreadPool()

它是一个缓存型的池子,须要建立线程的时候他会先查看有没有之前建立过的,若是有就回收,没有才会从新建立。适合执行一些生命周期较短的异步任务,它里面的线程都有一个time out限制,也就是说若是一个线程超过60s没有活动,那么这个线程将被移除。固然前面说的回收,确定是回收的没有time out 的线程。因此放入它里面的线程没必要担忧它的结束,超过60S不活动,会自动终止。

newFixedThreadPool(count)

这个线程池跟cache池相似,它也能够回收前面的线程,可是它的特殊之处在于同一时间它只容许固定数目的线程活动,实例化的时候能够限定一个线程数目,好比上面提到的5个线程同步执行,固然也能够根据CPU个数来动态设定线程个数,最好设置成核数的2N以下代码:

 int count = Runtime.getRuntime().availableProcessors() ;
ExecutorService executorService = Executors.newFixedThreadPool(count*2);

若是指定了线程数目,在手机性能较差的状况下可能会发生卡顿,ANR现象。fixed池子里面的线程应该没有time out或者是时间很长,基本不会超时。

newScheduledThreadPool(count)

能够实现一个定长的可延时或者周期执行的线程池;

newSingleThreadExceoutor()

能够实现一个只容许一个工做线程工做的线程池。这个池子里面只容许一个线程在活动,顺序完成全部的任务。能够用于数据库的操做,文件操做,或者是批量安装应用,卸载应用等不适合高并发但有可能IO阻塞以及影响UI相应的操做。

关于多线程就讲到这里,只是讲了一点基础知识,想要深刻了解的能够自行百度。

相关文章
相关标签/搜索