一、AsyncTask
AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UI。从实现上说,AsyncTask封装了Thread和Handler,通过AsyncTask可以更加方便的执行后台任务以及在主线程中访问UI,但是AsyncTask并不适合进行特别耗时的后台任务,耗时任务建议使用线程池。
四个核心方法
1、onPreExecute(),在主线程中执行,在异步任务执行之前,此方法会被调用,一般可以用于做一些准备工作。
2、doInBackground(Params ... params),在线程池中执行,此方法用于执行异步任务,params参数表示异步任务的输入参数。在此方法中可以通过publishProgress()方法更新任务进度,publishProgress方法会调用onProgressUpdate方法。该方法需要返回计算结果给onPostExecute。
3、onProgressUpdate(Progress ...values),在主线程中执行,当后台任务的执行进度发生改变时此方法被调用。
4、onPostExecute(Result result),在主线程中执行,在异步任务执行之后,此方法会被调用,其中result参数是后台任务的返回值,即doInBackground的返回值。
5、onCancelled(),当异步任务被取消时,该方法被调用,此时onPostExecute则不会被调用。
使用限制
1、之前的版本AsyncTask的对象必须在主线程中创建,但最新版本下AsyncTask可以在子线程中创建。
2、execute方法必须在UI线程调用。
3、不要再程序中直接调用onPreExecute()、onPostExecute、doInBackground和onProgressUpdate方法。
4、一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则会报运行时异常。
5、Android3.0以及后续的版本中,可以通过AsyncTask的executeOnExecutor方法来并行执行任务。
工作原理
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
@MainThread
public final AsyncTask<Params, Progress, Result> 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();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
sDefaultExecutor实际上是一个串行的线程池,一个进程中所有的AsyncTask全部在这个串行的线程池中排队执行。在executeOnExecutor方法中,AsyncTask的onPreExecute方法最先执行,然后线程池开始执行。
/**
* An {@link Executor} that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
*/
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
AsyncTask的排队执行过程:首先系统会把AsyncTask的Params参数封装为FutureTask对象,FutureTask是一个并发类,在这里它充当了Runnable的作用。接着FutureTask交给SerialExecutor.execute方法处理。在execute方法中,futureTask首先被插入到任务队列mTask中,如果这个时候没有正在活动的任务,则会调用scheduleNext方法执行下一个AsyncTask任务。当一个AsyncTask任务执行完后,AsyncTask会继续执行其他任务直到所有的任务都被执行为止。默认情况下,AsyncTask是串行执行的。
AsyncTask中有两个线程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一个Handler(InternalHandler),其中线程池SerialExecutor用于任务的排队,而线程池THREAD_POOL_EXECUTOR用于真正地执行任务,InternalHandler用于将执行环境从线程池切换到主线程。
在SerialExecutor中调用了FutureTask.run()。而在FutureTask.run方法中最后又会调用mWorker.call()方法,因此mWorker.call最终在线程池中执行。
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
##默认情况下handler为InternalHandler
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@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;
}
}
}
在mWorker.call()中,首先将mTaskInvoked置为true,表示当前任务已经被调用过了,然后执行AsyncTask.doInBackground方法,接着将其返回值传递给postResult方法。postResult方法会通过sHandler发送一个MESSAGE_POST_RESULT消息。sHandler是一个静态的Handler对象,为了能够将执行环境切换到主线程,sHandler必须在主线程中创建【其实按照现在的源码来看,我的理解是不需要在主线程中声明了,看下面代码】。
public AsyncTask(@Nullable Looper callbackLooper) {
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
}
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
默认情况下AsyncTask持有的mHandler即为sHandler,而目前默认给sHandler的looper为主线程Looper,因此就算在子线程中初始化了AsyncTask,sHandler的handleMessage方法依旧在主线程中执行。
sHandler收到MESSAGE_POST_RESULT消息后调用AsyncTask.finish()方法。
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
如果AsyncTask被取消执行了,那么回调mCancelled方法,否则调用onPostExecute方法。
自身理解
google的工程师在AsyncTask的构造方法中加入了Looper参数,意味AsyncTask目前拥有更自由的定制化程度,我们可以给它传入子线程下的Looper,同时当前AsyncTask的onPreExecute方法和onPostExecute方法均会在当前线程下回调而不是默认的主线程。
二、HandlerThread
HandlerThread继承了Thread,它是一种可以使用Handler的Thread,在run方法中通过Looper.prepare()创建消息队列,并通过Looper.loop()来开启消息循环。
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
private @Nullable Handler mHandler;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
/**
* Constructs a HandlerThread.
* @param name
* @param priority The priority to run the thread at. The value supplied must be from
* {@link android.os.Process} and not from java.lang.Thread.
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
/**
* @return a shared {@link Handler} associated with this thread
* @hide
*/
@NonNull
public Handler getThreadHandler() {
if (mHandler == null) {
mHandler = new Handler(getLooper());
}
return mHandler;
}
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
/**
* Quits the handler thread's looper safely.
* <p>
* Causes the handler thread's looper to terminate as soon as all remaining messages
* in the message queue that are already due to be delivered have been handled.
* Pending delayed messages with due times in the future will not be delivered.
* </p><p>
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
* For example, the {@link Handler#sendMessage(Message)} method will return false.
* </p><p>
* If the thread has not been started or has finished (that is if
* {@link #getLooper} returns null), then false is returned.
* Otherwise the looper is asked to quit and true is returned.
* </p>
*
* @return True if the looper looper has been asked to quit or false if the
* thread had not yet started running.
*/
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
}
它与普通Thread有显著的不同之处,普通Thread主要用于在run方法中执行一个耗时任务,而HandlerThread在内部创建了消息队列,外部需要通过Handler的消息方式来通知HandlerThread执行一个具体的任务。
当明确不需要再使用HandlerThread时,可以通过它的quit或者quitSafely方法来终止线程的执行。
三、IntentService
IntentService继承自Service且自身是一个抽象类,可用于执行后台耗时的任务,当任务执行后它会自动停止。IntentService的优先级比单纯的线程高很多,适合执行一些高优先级的后台任务。
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
当IntentService第一次启动时,会创建一个HandlerThread,通过它的Looper创建mServiceHandler。
启动IntentService时,onStartCommand方法被调用,而在onStartCommand中又调用了onStart方法。
onStart方法中包装一个Message对象,将intent交给mServiceHandler处理,最终由onHandleIntent()方法处理传入的Itnent对象,这里的intent与外界通过startService(Intent intent)方法中传递的Intent对象内容一致,通过这个Intent即可解析出外界启动IntentService时传递的参数,通过参数区分具体的后台任务。
当onHandleIntent方法执行结束后,IntentService会通过stopSelf(int startId)方法尝试停止服务,这里之所以采用stopSelf(int startId)而不是stopSelf()停止服务,因为stopSelft()会立刻停止服务,而这个时候可能还有其他消息未处理,stopSelf(int startId)会等待所有的消息处理完毕后才终止服务。一般来说,stopSelf(int startId)在尝试停止服务之前会判断最近启动服务的次数是否和staratId相等,如果相等就立刻停止服务,不相等则不停止服务。
由于IntentService内部通过消息的方式向HandlerThread请求执行任务,Handler中的Looper是顺序处理消息的,这就意味着IntentService也是顺序执行后台任务,当有多个后台任务同时纯在时,这些后台任务会按照外界发起的顺序排队执行。