AsyncTask类封装了两个线程池:serialExecutor,以及THREAD_POOL_EXECUTOR,以及一个Handler.其工作原理主要围绕这三个主体展开。
首先简单介绍下AsyncTask类,主要有4个方法,onPreExecute(),doInBackground(),onProgressUpdate(),onPostExecute();其执行顺序依次进行。除了doInBackground()方法外,其它方法都在主线程运行。
举个栗子:这个类模拟了下载文件功能,并以对话框形式显示了下载进度。可以看见,第一个参数URL,作为doInBackground()方法的参数,它是一个数组型参数,Integer是进度条值得类型(第三个方法参数),Long作为最后一个方法的参数,它实际上是doInBackground()方法执行完的返回值类型
private class TestAsyncTask extends AsyncTask<URL,Integer,Long>{
// onPreExecute()
protected Long doInbackground(URL... urls){
int count =urls.length;
long totalSize =0;
for( int i=0;i<count;i++){
totalSize+ =Downloader.downloadFile(urls[i]);
publishPregress((int)((i/(float)count)*100));
if(isCancelled())
break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress){
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result){
showDialog("Download"+result+"bytes");
}
}
调用方式:new TestAsyncTask().execute(url1,url2...)
限制:1.AsynTask对象只能在主线程创建,execute()方法只能在主线程调用
2.一个AsyncTask对象只能执行一次.
PS:异步任务(AsyncTask)默认在1.6以前是串行执行,在1.6到3.0之间又并行执行,3.0之后又变为串行执行,不过3.0后可以使用AysncTask的executeOnExecutor()方法并行执行任务
工作原理:
首先从AsyncTask的execute方法开始,execute方法调用了 executeOnExecutor()方法。这个方法传入两个参数并且执行了OnPreExecute方法,一个就是前面提到的第一个线程池serialExecutor,另一个是execute传入的参数(上面的url).serialExecutor不是实际上用于执行任务的线程池,而是将参数url封装FutureTask对象(通过该类的execute方法),将其放入任务队列中。该类有两个方法,一个是execute(),一个是scheduleNext().前者作用已经说过,后者的作用当一个任务执行完,则执行该方法进行下一个任务,这个任务才是实际的任务,其中调用了THREAD#POOL#EXECUTOR.execute(Runnable r)方法,这个线程池就是前面提到的第二个线程池,也是真正意义上执行任务的线程池。
在AsyncTask构造方法中初始化了一个WorkerRunnable对象,其中的call方法会被封装后的FutureTask(任务参数封装体)对象调用,call方法调用了postResult(doInBackgound(mParams))方法,此方法调用Handler向MessageQueue发送了一个消息,并返回了Result对象(即最后一个方法中的参数),而这个过程是从工作线程(执行任务的线程)传递Result对象到主线程(最后一个方法在主线程中执行),其间用到了最后一个主体,InternalHandler,这个Handler接收一个消息,根据这个消息的值区分传送到第三个方法还是第四个方法(msg.what值分别为MESSAGE#POST#PROGRESS,MESSAGE#POST#RESULT)