1 AsyncTask实现的原理,和适用的优缺点

AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程.

使用的优点:

l 简单,快捷

l 过程可控

使用的缺点:

l 在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来.

2 Handler异步实现的原理和适用的优缺点

在Handler 异步实现时,涉及到 Handler, Looper, Message,Thread四个对象,实现异步的流程是主线程启动Thread(子线程)àthread(子线程)运行并生成Message- àLooper获取Message并传递给HandleràHandler逐个获取Looper中的Message,并进行UI变更。

使用的优点:

l 结构清晰,功能定义明确

l 对于多个后台任务时,简单,清晰

AsyncTask这个类感觉使用比较简单,就是实现其中几个方法,onPreExecute()方法是在任务刚开始运行时执行的一些初始化操作,比如初 始化一个进度条等等,然后就执行doInBackground()方法这里面主要放业务操作,比如查询数据库等,在这个方法执行的时候会调用 onProgressUpdate(),可以在这个方法中更新UI界面,最后是调用onPostExecute()方法,当得到业务结果后就可以在这个方 法中返回给UI线程,也可以关闭一些执行这个业务时开的一些资源。大家可以看得出AsyncTask这个类是一个泛型类,这个类的三个参数以此对应 doInBackground(String... params),onProgressUpdate(String... values),onPostExecute(String result)的参数,很形象的···如果不需要传参和返回值,可以用Void代替。而doInBackground(String... params)方法的返回值也就是onPostExecute(String result)方法的参数值,因为doInBackground方法执行后返回的值是在onPostExecute(String result)中处理的。

用handler方式处理需要知道与handler相关的几个组件,Looper和Queue,其实Looper的作用就是把handler发送的消息放 到Queue中,并把消息广播给所有与这个Queue相关的handler,而Queue一般是主线程开启的时候就给这个线程分配了一个,所以你要与UI 主线程通信必须用于这个Queue相关联的handler对象才行,一般handler对象在那个线程中创建的就与那个线程的queue关联,所以在UI 线程中创建的handler对象就与UI线程通讯,这样我们就可以在子线程中发送消息给主线程,实现更新UI的功能。那主线程又是怎么处理子线程发送的消 息的呢?其实在生成handler对象的时候我们就要实现handler对象的handleMessage()方法这个方法就是主线程接受并处理子线程发 送过来的消息的方法,从而实现 更新UI线程的功能。

很多网友可能发现Android平台很多应用使用的都是AsyncTask,而并非Thread和Handler去更新UI,这里给大家说下他们到底有什 么区别,我们平时应该使用哪种解决方案。从Android 1.5开始系统将AsyncTask引入到android.os包中,过去在很早1.1和1.0 SDK时其实官方将其命名为UserTask,其内部是JDK 1.5开始新增的concurrent库,做过J2EE的网友可能明白并发库效率和强大性,比Java原始的Thread更灵活和强大,但对于轻量级的使 用更为占用系统资源。Thread是Java早期为实现多线程而设计的,比较简单不支持concurrent中很多特性在同步和线程池类中需要自己去实现 很多的东西,对于分布式应用来说更需要自己写调度代码,而为了Android UI的刷新Google引入了Handler和Looper机制,它们均基于消息实现,有时可能消息队列阻塞或其他原因无法准确的使用。

推荐大家使用AsyncTask代替Thread+Handler的方式,不仅调用上更为简单,经过实测更可靠一些,Google在Browser中大量 使用了异步任务作为处理耗时的I/O操作,比如下载文件、读写数据库等等,它们在本质上都离不开消息,但是AsyncTask相比Thread加 Handler更为可靠,更易于维护,但AsyncTask缺点也是有的比如一旦线程开启即dobackground方法执行后无法给线程发送消息,仅能 通过预先设置好的标记来控制逻辑,当然可以通过线程的挂起等待标志位的改变来通讯,对于某些应用Thread和Handler以及Looper可能更灵 活。

本文主要讲解下AsyncTask的使用以及Handler的应用

首先,我们得明确下一个概念,什么是UI线程。顾名思义,ui线程就是管理着用户界面的那个线程!

android的ui线程操作并不是安全的,并且和用户直接进行界面交互的操作都必须在ui线程中进行才可以。这种模式叫做单线程模式。

我们在单线程模式下编程一定要注意:不要阻塞ui线程、确保只在ui线程中访问ui组件

当我们要执行一个复杂耗时的算法并且最终要将计算结果反映到ui上时,我们会发现,我们根本没办法同时保证上面的两点要求;我们肯定会想到开启一个新的线程,让这个复杂耗时的任务到后台去执行,但是执行完毕了呢?我们发现,我们无法再与ui进行交互了。

为了解决这种情况,android为我们提供了很多办法。

1)、handler和message机制:通过显示的抛出、捕获消息与ui进行交互;

2)、Activity.runOnUiThread(Runnable):如果当前线程为ui线程,则立即执行;否则,将参数中的线程操作放入到ui线程的事件队列中,等待执行。

3)、View.post(Runnable):将操作放入到message队列中,如果放入成功,该操作将会在ui线程中执行,并返回true,否则返回false

4)、View.postDelayed(Runnable, long)跟第三条基本一样,只不过添加了一个延迟时间。

5)、android1.5以后为我们提供了一个工具类来搞定这个问题AsyncTask.

AsyncTask是抽象类,定义了三种泛型类型 Params,Progress,Result。

Params 启动任务执行的输入参数,比如HTTP请求的URL

Progress 后台任务执行的百分比。

Result 后台执行任务最终返回的结果,比如String

用程序调用,开发者需要做的就是实现这些方法。

1) 子类化AsyncTask

2) 实现AsyncTask中定义的下面一个或几个方法

onPreExecute(),该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。

doInBackground(Params…),将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。

onProgressUpdate(Progress…),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。

onPostExecute(Result),在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.

为了正确的使用AsyncTask类,以下是几条必须遵守的准则:

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

2) execute方法必须在UI thread中调用

3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params…), onProgressUpdate(Progress…)这几个方法

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


下面介绍最本质的多线程:hanlder和message机制:

为何需要多线程:

在日常应用中,我们通常需要处理一些“后台,用户不可见”的操作,例如说,我们需要下载一个音乐,要是你的应用必须等用户下载完成之后才可以进行别的操 作,那肯定让用户非常的不爽。这时候,我们通常的做法是,让这些操作去后台执行,然后等后台执行完毕之后,再给用户弹出相应的提示信息。这时候,我们就需 要使用多线程机制,然后通过创建一个新的线程来执行这些操作。

明白了,实现需求,我们就准备着手实现了。但是,经过进一步的了解,我们悲剧的发现,android中的线程机制是,只能在UI线程中和用户进行交互。当 我们创建了一个新线程,执行了一些后台操作,执行完成之后,我们想要给用户弹出对话框以确认,但是却悲剧的发现,我们根本无法返回UI主线程了。

(说明:何为UI线程:UI线程就是你当前看到的这些交互界面所属的线程)。

这时候,我们如果想要实现这些功能,我们就需要一个android为我们提供的handler和message机制。

先讲解下编程机制:

我们通常在UI线程中创建一个handler,handler相当于一个处理器,它主要负责处理和绑定到该handler的线程中的message。每一 个handler都必须关联一个looper,并且两者是一一对应的,注意,这点很重要哦!此外,looper负责从其内部的messageQueue中 拿出一个个的message给handler进行处理。因为我们这里handler是在UI线程中实现的,所以经过这么一个handler、 message机制,我们就可以回到UI线程中了。

何为handler:处理后台进程返回数据的工作人员。

何为message:后台进程返回的数据,里面可以存储bundle等数据格式

何为messageQueue:是线程对应looper的一部分,负责存储从后台进程中抛回的和当前handler绑定的message,是一个队列。

何为looper:looper相当于一个messageQueue的管理人员,它会不停的循环的遍历队列,然后将符合条件的message一个个的拿出来交给handler进行处理。

注意,handler是在UI线程中声明的,如果我们直接用类似代码执行一个线程的话,实际上并没有创建一个新的线程,因为handler已经跟默认的UI线程中的looper绑定了。

如果有兴趣的话,可以去看下Handler的默认空构造函数便知道原因了,里面直接绑定了当前UI线程的looper。

下面给出一个比较简单,并且实用的实例。

这2种方式都可以实现,但是他们的区别在哪里?优缺点各是什么?

(1)、AsyncTask是封装好的线程池,比起Thread+Handler的方式,AsyncTask在操作UI线程上更方便,因为onPreExecute()、onPostExecute()及更新UI方法onProgressUpdate()均运行在主线程中,这样就不用Handler发消息处理了;

(2)、我不太同意封装好就会影响性能的说法,在我实际的运用中,真正的缺点来自于AsyncTask的全局线程池只有5个工作线程,也就是说,一个APP如果运用AsyncTask技术来执行线程,那么同一时间最多只能有5个线程同时运行,其他线程将被阻塞(注:不运用AsyncTask执行的线程,也就是自己new出来的线程不受此限制),所以AsyncTask不要用于多线程取网络数据,因为很可能这样会产生阻塞,从而降低效率。

三. 能否同时并发100+asynctask呢?

AsyncTask用的是线程池机制,容量是128,最多同时运行5个core线程,剩下的排队。

2、AsyncTask是否异步

public class MainService extends Service{private static Task task;//当前执行任务private static Map<String, Activity> allActivitys = new HashMap<String, Activity>();//缓存activity集合private static ExecutorService exec = Executors.newSingleThreadExecutor();@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);MainAsyncTask asyncTask = new MainAsyncTask();//asyncTask.execute(task);//asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task);//asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);//asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task);asyncTask.executeOnExecutor(exec, task);}private final class MainAsyncTask extends AsyncTask<Object, Integer, Object>{private Task task;@Overrideprotected Object doInBackground(Object... params) {Object result = null;task = (Task)params[0];switch (task.getTaskID()) {case Task.TASK_USER_LOGIN:try {Thread.sleep(3000);System.out.println("任务"+task.getTaskID()+" Thread id: "+Thread.currentThread().getId());} catch (InterruptedException e) {e.printStackTrace();}break;case 2:System.out.println("任务"+task.getTaskID()+" Thread id: "+Thread.currentThread().getId());break;}return result;}@Overrideprotected void onPostExecute(Object result) {super.onPostExecute(result);ActivityInterFace aif;switch (task.getTaskID()) {case Task.TASK_USER_LOGIN:aif = (ActivityInterFace)allActivitys.get("LoginActivity");aif.refresh(1, result);break;case 2:aif = (ActivityInterFace)allActivitys.get("LoginActivity");aif.refresh(2, result);break;default:break;}}}/** * 添加新任务 * @param task */public static void addTask(Context context, Task task) {MainService.task = task;context.startService(new Intent("mainService"));}/** * 缓存activity * @param activity */public static void addActivity(Activity activity) {String path = activity.getClass().getName();String name = path.substring(path.lastIndexOf(".")+1);allActivitys.put(name, activity);}@Overridepublic IBinder onBind(Intent intent) {return null;}}

当我执行两次调用asyncTask.execute(task);时发现只有当第一次的任务完成后才执行下一下任务!!怎么回事?

AyncTask不是号称异步线程池吗?既然是线程池那么多任务执行时应该可以并发执行啊,至少两个任务可以并发执

行,以前看过一个视频,人家的就可以啊!纠结了一下午,通过查阅资料和自己的动手实验终于把问题搞明白了。

原来在SDK3.0以前的版本执行asyncTask.execute(task);时的确是多线程并发执行的,线程池大小为5,最大可大

128个,google在3.0以后的版本中做了修改,将asyncTask.execute(task);修改为了顺序执行,即只有当一个的实

的任务完成后在执行下一个实例的任务。

那么怎么才能并发执行呢,很简单,3.0后新增了一个方法executeOnExecutor(Executor
exec,
Object... params),

该方法接受2个参数,第一个是Executor,第二个是任务参数。第一个是线程池实例,google为我们预定义了两种:

一种是AsyncTask.SERIAL_EXECUTOR,第二种是AsyncTask.THREAD_POOL_EXECUTOR,顾名思义,第一

其实就像3.0以后的execute方法,是顺序执行的。第二种就是3.0以前的execute方法,是可以并发执行的。我们直

接用asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);就可以多任务并发执行了。

既然executeOnExecutor第一个参数是Executor,那么我们可以自定义Executor吗?当然可以,Executor主要由四

类型newCachedThreadPool,newFixedThreadPool,newScheduledThreadPool,newSingleThreadExecutor

(具体使用解析可以看我上一篇文章点击打开链接),可是当我这样使用

asyncTask.executeOnExecutor(Executors.newFixedThreadPool(1), task);或者

asyncTask.executeOnExecutor(Executors.newSingleThreadExecutor, task);并没有像我想象的与

asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task);那样是单线程顺序执行,而是像

asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);是多线程并发执行的,我不是

已经规定newFixedThreadPool的线程池数量是1或者是newSingleThreadExecutor单线程了么!怎么回事呢?原来程

序在每次调用asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task)时会获取一个新的Executor对

象,这个对象内的线程只执行对应的task,所以无论哪种情况每个task都有一个新的线程来执行,即并发执行。

知道原因就好办了,我们定义个一全局静态变量

private static ExecutorService exec = Executors.newSingleThreadExecutor();程序在每次调用

asyncTask.executeOnExecutor(exec, task);时是使用的同一个Executor,执行效果如下:

当Executor类型为:private static ExecutorService exec = Executors.newFixedThreadPool(2);只有两个线程在执行

任务

当Executor类型为:private static ExecutorService exec = Executors.newSingleThreadExecutor();只有一个线程在执行任务

package com.example.ztestandroid;import java.util.Calendar;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import android.app.Activity;import android.os.AsyncTask;import android.os.Bundle;import com.example.ztestandroid.bean.Task;public class MainActivity extends  Activity { private static ExecutorService exec = Executors.newSingleThreadExecutor();  @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);System.out.println("start time: "+Calendar.SECOND);for (int i = 1; i < 10; i++) {int count  = i%2==0?1:2;Task task = new Task(count, "task "+i);MainAsyncTask asyncTask = new MainAsyncTask();/* * 顺序执行,AsyncTask里面有5个核心线程,最大128个 * 01-14 11:30:47.000: I/System.out(17418): start time: 1301-14 11:30:47.000: I/System.out(17418): end time: 1301-14 11:30:47.000: I/System.out(17418): 任务2 task 1 Thread id: 840 seconds: 142120624700801-14 11:30:50.020: I/System.out(17418): 任务1 task 2 Thread id: 841 seconds: 142120625002801-14 11:30:50.025: I/System.out(17418): 任务2 task 3 Thread id: 842 seconds: 142120625003301-14 11:30:53.030: I/System.out(17418): 任务1 task 4 Thread id: 843 seconds: 142120625303701-14 11:30:53.040: I/System.out(17418): 任务2 task 5 Thread id: 844 seconds: 142120625304701-14 11:30:56.050: I/System.out(17418): 任务1 task 6 Thread id: 844 seconds: 142120625605301-14 11:30:56.050: I/System.out(17418): 任务2 task 7 Thread id: 844 seconds: 142120625605501-14 11:30:59.050: I/System.out(17418): 任务1 task 8 Thread id: 844 seconds: 142120625905701-14 11:30:59.050: I/System.out(17418): 任务2 task 9 Thread id: 844 seconds: 1421206259058 *///        asyncTask.execute(task);          // 和asyncTask.execute(task)执行结果相同,顺序执行。//asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, task); /* * 可以看出是异步执行,线程池里面最多有5个线程 * 01-14 11:43:14.115: I/System.out(18208): start time: 1301-14 11:43:14.115: I/System.out(18208): end time: 1301-14 11:43:14.115: I/System.out(18208): 任务2 task 1 Thread id: 880 seconds: 142120699412101-14 11:43:14.115: I/System.out(18208): 任务2 task 3 Thread id: 877 seconds: 142120699412201-14 11:43:14.115: I/System.out(18208): 任务2 task 5 Thread id: 876 seconds: 142120699412201-14 11:43:14.115: I/System.out(18208): 任务2 task 7 Thread id: 877 seconds: 142120699412301-14 11:43:14.115: I/System.out(18208): 任务2 task 9 Thread id: 877 seconds: 142120699412301-14 11:43:17.115: I/System.out(18208): 任务1 task 2 Thread id: 880 seconds: 142120699712201-14 11:43:17.115: I/System.out(18208): 任务1 task 6 Thread id: 878 seconds: 142120699712301-14 11:43:17.115: I/System.out(18208): 任务1 task 8 Thread id: 876 seconds: 142120699712301-14 11:43:17.115: I/System.out(18208): 任务1 task 4 Thread id: 879 seconds: 1421206997123 */        asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, task);  /* * 异步执行 * 01-14 11:28:06.915: I/System.out(17143): start time: 1301-14 11:28:06.915: I/System.out(17143): 任务2 task 1 Thread id: 837 seconds: 142120608692401-14 11:28:06.920: I/System.out(17143): 任务2 task 3 Thread id: 839 seconds: 142120608692501-14 11:28:06.920: I/System.out(17143): 任务2 task 5 Thread id: 841 seconds: 142120608692601-14 11:28:06.920: I/System.out(17143): 任务2 task 7 Thread id: 843 seconds: 142120608692601-14 11:28:06.920: I/System.out(17143): end time: 1301-14 11:28:06.920: I/System.out(17143): 任务2 task 9 Thread id: 845 seconds: 142120608692701-14 11:28:09.925: I/System.out(17143): 任务1 task 2 Thread id: 838 seconds: 142120608992601-14 11:28:09.925: I/System.out(17143): 任务1 task 4 Thread id: 840 seconds: 142120608992701-14 11:28:09.925: I/System.out(17143): 任务1 task 6 Thread id: 842 seconds: 142120608992701-14 11:28:09.925: I/System.out(17143): 任务1 task 8 Thread id: 844 seconds: 1421206089927 *///asyncTask.executeOnExecutor(Executors.newFixedThreadPool(2), task);      /*     * 执行结果:     *   任务1 task 2 Thread id: 816 seconds: 1421205791881 任务2 task 3 Thread id: 816 seconds: 1421205791882 任务1 task 4 Thread id: 816 seconds: 1421205794883 任务2 task 5 Thread id: 816 seconds: 1421205794883 任务1 task 6 Thread id: 816 seconds: 1421205797884 任务2 task 7 Thread id: 816 seconds: 1421205797885 任务1 task 8 Thread id: 816 seconds: 1421205800886 任务2 task 9 Thread id: 816 seconds: 1421205800887     *///asyncTask.executeOnExecutor(exec, task);  }System.out.println("end time: "+Calendar.SECOND);} private final class MainAsyncTask extends AsyncTask<Object, Integer, Object>{          private Task task;          @Override          protected Object doInBackground(Object... params) {              Object result = null;              task = (Task)params[0];              switch (task.getTaskID()) {              case Task.TASK_USER_LOGIN:                  try {                      Thread.sleep(3000);                      System.out.println("任务"+task.getTaskID()+" "+ task.getTask()+" Thread id: "+Thread.currentThread().getId()+" seconds: "+System.currentTimeMillis());                  } catch (InterruptedException e) {                      e.printStackTrace();                  }                  break;              case 2:               System.out.println("任务"+task.getTaskID()+" "+ task.getTask()+" Thread id: "+Thread.currentThread().getId()+" seconds: "+System.currentTimeMillis());                  break;              }              return result;          }          @Override          protected void onPostExecute(Object result) {              super.onPostExecute(result);          }      }  }


3、AsyncTask源码分析

public abstract class AsyncTask {    private static final String LOG_TAG = AsyncTask;//获取当前的cpu核心数    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();//线程池核心容量    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;//线程池最大容量    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;//过剩的空闲线程的存活时间    private static final int KEEP_ALIVE = 1;//ThreadFactory 线程工厂,通过工厂方法newThread来获取新线程    private static final ThreadFactory sThreadFactory = new ThreadFactory() {//原子整数,可以在超高并发下正常工作        private final AtomicInteger mCount = new AtomicInteger(1);        public Thread newThread(Runnable r) {            return new Thread(r, AsyncTask # + mCount.getAndIncrement());        }    };//静态阻塞式队列,用来存放待执行的任务,初始容量:128个    private static final BlockingQueue sPoolWorkQueue =            new LinkedBlockingQueue(128);    /**     * 静态并发线程池,可以用来并行执行任务,尽管从3.0开始,AsyncTask默认是串行执行任务 * 但是我们仍然能构造出并行的AsyncTask     */    public static final Executor THREAD_POOL_EXECUTOR            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);    /**     * 静态串行任务执行器,其内部实现了串行控制, * 循环的取出一个个任务交给上述的并发线程池去执行     */    public static final Executor SERIAL_EXECUTOR = new SerialExecutor();//消息类型:发送结果    private static final int MESSAGE_POST_RESULT = 0x1;//消息类型:更新进度    private static final int MESSAGE_POST_PROGRESS = 0x2;/**静态Handler,用来发送上述两种通知,采用UI线程的Looper来处理消息 * 这就是为什么AsyncTask必须在UI线程调用,因为子线程 * 默认没有Looper无法创建下面的Handler,程序会直接Crash */    private static final InternalHandler sHandler = new InternalHandler();//默认任务执行器,被赋值为串行任务执行器,就是它,AsyncTask变成串行的了    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;//如下两个变量我们先不要深究,不影响我们对整体逻辑的理解    private final WorkerRunnable mWorker;    private final FutureTask mFuture;//任务的状态 默认为挂起,即等待执行,其类型标识为易变的(volatile)    private volatile Status mStatus = Status.PENDING;    //原子布尔型,支持高并发访问,标识任务是否被取消    private final AtomicBoolean mCancelled = new AtomicBoolean();//原子布尔型,支持高并发访问,标识任务是否被执行过    private final AtomicBoolean mTaskInvoked = new AtomicBoolean();/*串行执行器的实现,我们要好好看看,它是怎么把并行转为串行的 *目前我们需要知道,asyncTask.execute(Params ...)实际上会调用 *SerialExecutor的execute方法,这一点后面再说明。也就是说:当你的asyncTask执行的时候, *首先你的task会被加入到任务队列,然后排队,一个个执行 */    private static class SerialExecutor implements Executor {//线性双向队列,用来存储所有的AsyncTask任务        final ArrayDeque mTasks = new ArrayDeque();//当前正在执行的AsyncTask任务        Runnable mActive;        public synchronized void execute(final Runnable r) {//将新的AsyncTask任务加入到双向队列中            mTasks.offer(new Runnable() {                public void run() {                    try {//执行AsyncTask任务                        r.run();                    } finally {//当前AsyncTask任务执行完毕后,进行下一轮执行,如果还有未执行任务的话//这一点很明显体现了AsyncTask是串行执行任务的,总是一个任务执行完毕才会执行下一个任务                        scheduleNext();                    }                }            });//如果当前没有任务在执行,直接进入执行逻辑            if (mActive == null) {                scheduleNext();            }        }        protected synchronized void scheduleNext() {//从任务队列中取出队列头部的任务,如果有就交给并发线程池去执行            if ((mActive = mTasks.poll()) != null) {                THREAD_POOL_EXECUTOR.execute(mActive);            }        }    }    /**     * 任务的三种状态     */    public enum Status {        /**         * 任务等待执行         */        PENDING,        /**         * 任务正在执行         */        RUNNING,        /**         * 任务已经执行结束         */        FINISHED,    }    /** 隐藏API:在UI线程中调用,用来初始化Handler */    public static void init() {        sHandler.getLooper();    }    /** 隐藏API:为AsyncTask设置默认执行器 */    public static void setDefaultExecutor(Executor exec) {        sDefaultExecutor = exec;    }    /**     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.     */    public AsyncTask() {        mWorker = new WorkerRunnable() {            public Result call() throws Exception {                mTaskInvoked.set(true);                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                //noinspection unchecked                return postResult(doInBackground(mParams));            }        };        mFuture = new FutureTask(mWorker) {            @Override            protected void done() {                try {                    postResultIfNotInvoked(get());                } catch (InterruptedException e) {                    android.util.Log.w(LOG_TAG, e);                } catch (ExecutionException e) {                    throw new RuntimeException(An error occured while executing doInBackground(),                            e.getCause());                } catch (CancellationException e) {                    postResultIfNotInvoked(null);                }            }        };    }    private void postResultIfNotInvoked(Result result) {        final boolean wasTaskInvoked = mTaskInvoked.get();        if (!wasTaskInvoked) {            postResult(result);        }    }//doInBackground执行完毕,发送消息    private Result postResult(Result result) {        @SuppressWarnings(unchecked)        Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,                new AsyncTaskResult(this, result));        message.sendToTarget();        return result;    }    /**     * 返回任务的状态     */    public final Status getStatus() {        return mStatus;    }    /** * 这个方法是我们必须要重写的,用来做后台计算 * 所在线程:后台线程     */    protected abstract Result doInBackground(Params... params);    /** * 在doInBackground之前调用,用来做初始化工作 * 所在线程:UI线程     */    protected void onPreExecute() {    }    /** * 在doInBackground之后调用,用来接受后台计算结果更新UI * 所在线程:UI线程     */    protected void onPostExecute(Result result) {    }    /**     * Runs on the UI thread after {@link #publishProgress} is invoked.     /** * 在publishProgress之后调用,用来更新计算进度 * 所在线程:UI线程     */    protected void onProgressUpdate(Progress... values) {    }     /** * cancel被调用并且doInBackground执行结束,会调用onCancelled,表示任务被取消 * 这个时候onPostExecute不会再被调用,二者是互斥的,分别表示任务取消和任务执行完成 * 所在线程:UI线程     */    @SuppressWarnings({UnusedParameters})    protected void onCancelled(Result result) {        onCancelled();    }            protected void onCancelled() {    }    public final boolean isCancelled() {        return mCancelled.get();    }    public final boolean cancel(boolean mayInterruptIfRunning) {        mCancelled.set(true);        return mFuture.cancel(mayInterruptIfRunning);    }    public final Result get() throws InterruptedException, ExecutionException {        return mFuture.get();    }    public final Result get(long timeout, TimeUnit unit) throws InterruptedException,            ExecutionException, TimeoutException {        return mFuture.get(timeout, unit);    }    /**     * 这个方法如何执行和系统版本有关,在AsyncTask的使用规则里已经说明,如果你真的想使用并行AsyncTask, * 也是可以的,只要稍作修改 * 必须在UI线程调用此方法     */    public final AsyncTask execute(Params... params) {//串行执行        return executeOnExecutor(sDefaultExecutor, params);//如果我们想并行执行,这样改就行了,当然这个方法我们没法改//return executeOnExecutor(THREAD_POOL_EXECUTOR, params);    }    /**     * 通过这个方法我们可以自定义AsyncTask的执行方式,串行or并行,甚至可以采用自己的Executor * 为了实现并行,我们可以在外部这么用AsyncTask: * asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Params... params); * 必须在UI线程调用此方法     */    public final AsyncTask executeOnExecutor(Executor exec,            Params... params) {        if (mStatus != Status.PENDING) {            switch (mStatus) {                case RUNNING:                    throw new IllegalStateException(Cannot execute task:                            +  the task is already running.);                case FINISHED:                    throw new IllegalStateException(Cannot execute task:                            +  the task has already been executed                             + (a task can be executed only once));            }        }        mStatus = Status.RUNNING;//这里#onPreExecute会最先执行        onPreExecute();        mWorker.mParams = params;//然后后台计算#doInBackground才真正开始        exec.execute(mFuture);//接着会有#onProgressUpdate被调用,最后是#onPostExecute        return this;    }    /**     * 这是AsyncTask提供的一个静态方法,方便我们直接执行一个runnable     */    public static void execute(Runnable runnable) {        sDefaultExecutor.execute(runnable);    }    /** * 打印后台计算进度,onProgressUpdate会被调用     */    protected final void publishProgress(Progress... values) {        if (!isCancelled()) {            sHandler.obtainMessage(MESSAGE_POST_PROGRESS,                    new AsyncTaskResult(this, values)).sendToTarget();        }    }//任务结束的时候会进行判断,如果任务没有被取消,则onPostExecute会被调用    private void finish(Result result) {        if (isCancelled()) {            onCancelled(result);        } else {            onPostExecute(result);        }        mStatus = Status.FINISHED;    }//AsyncTask内部Handler,用来发送后台计算进度更新消息和计算完成消息    private static class InternalHandler extends Handler {        @SuppressWarnings({unchecked, RawUseOfParameterizedType})        @Override        public void handleMessage(Message msg) {            AsyncTaskResult result = (AsyncTaskResult) msg.obj;            switch (msg.what) {                case MESSAGE_POST_RESULT:                    // There is only one result                    result.mTask.finish(result.mData[0]);                    break;                case MESSAGE_POST_PROGRESS:                    result.mTask.onProgressUpdate(result.mData);                    break;            }        }    }    private static abstract class WorkerRunnable implements Callable {        Params[] mParams;    }    @SuppressWarnings({RawUseOfParameterizedType})    private static class AsyncTaskResult {        final AsyncTask mTask;        final Data[] mData;        AsyncTaskResult(AsyncTask task, Data... data) {            mTask = task;            mData = data;        }    }}



更多相关文章

  1. Android(安卓)消息处理机制(Looper、Handler、MessageQueue,Messa
  2. 上传音乐到Android模拟器的SD卡,并在Android模拟器上播放
  3. Android(安卓)Activity背景半透明设置方法
  4. Android中的软件安全和逆向分析[一]—apk反编译破解以及java汇编
  5. Java中的Timer和TimerTask在Android中的用法
  6. Python+PyQT5的子线程更新UI界面的实例
  7. Android(安卓)高版本(8、9、10)查看手机中进程信息、线程信息
  8. Android中Looper讲解
  9. Android实现定时器的几种方法

随机推荐

  1. ListView 常用属性 详解
  2. Android UI设计随笔
  3. Android的status bar分析
  4. Android四大组件之 BroadcastReceiver
  5. android开发必看资源URL
  6. Titanium Studio
  7. Feel Android Studio(1)Install and Upda
  8. Android TextView 换行
  9. android界面无标题栏和全屏效果的实现方
  10. 【Android 应用开发】Ubuntu 下 Android