一玩焰、AsyncTask
AsyncTask是一種輕量級(jí)的異步任務(wù)類逆粹,它可以在線程池中執(zhí)行后臺(tái)任務(wù)募疮,然后把執(zhí)行的進(jìn)度和最終結(jié)果傳遞給主線程并在主線程中更新UI。從實(shí)現(xiàn)上說僻弹,AsyncTask封裝了Thread和Handler阿浓,通過AsyncTask可以更加方便的執(zhí)行后臺(tái)任務(wù)以及在主線程中訪問UI,但是AsyncTask并不適合進(jìn)行特別耗時(shí)的后臺(tái)任務(wù)蹋绽,耗時(shí)任務(wù)建議使用線程池芭毙。
四個(gè)核心方法
1、onPreExecute()卸耘,在主線程中執(zhí)行退敦,在異步任務(wù)執(zhí)行之前,此方法會(huì)被調(diào)用蚣抗,一般可以用于做一些準(zhǔn)備工作侈百。
2、doInBackground(Params ... params)翰铡,在線程池中執(zhí)行钝域,此方法用于執(zhí)行異步任務(wù),params參數(shù)表示異步任務(wù)的輸入?yún)?shù)锭魔。在此方法中可以通過publishProgress()方法更新任務(wù)進(jìn)度例证,publishProgress方法會(huì)調(diào)用onProgressUpdate方法。該方法需要返回計(jì)算結(jié)果給onPostExecute迷捧。
3织咧、onProgressUpdate(Progress ...values),在主線程中執(zhí)行漠秋,當(dāng)后臺(tái)任務(wù)的執(zhí)行進(jìn)度發(fā)生改變時(shí)此方法被調(diào)用烦感。
4、onPostExecute(Result result)膛堤,在主線程中執(zhí)行,在異步任務(wù)執(zhí)行之后晌该,此方法會(huì)被調(diào)用肥荔,其中result參數(shù)是后臺(tái)任務(wù)的返回值绿渣,即doInBackground的返回值。
5燕耿、onCancelled()中符,當(dāng)異步任務(wù)被取消時(shí),該方法被調(diào)用誉帅,此時(shí)onPostExecute則不會(huì)被調(diào)用淀散。
使用限制
1、之前的版本AsyncTask的對(duì)象必須在主線程中創(chuàng)建蚜锨,但最新版本下AsyncTask可以在子線程中創(chuàng)建档插。
2、execute方法必須在UI線程調(diào)用亚再。
3郭膛、不要再程序中直接調(diào)用onPreExecute()、onPostExecute氛悬、doInBackground和onProgressUpdate方法则剃。
4、一個(gè)AsyncTask對(duì)象只能執(zhí)行一次如捅,即只能調(diào)用一次execute方法棍现,否則會(huì)報(bào)運(yùn)行時(shí)異常。
5镜遣、Android3.0以及后續(xù)的版本中己肮,可以通過AsyncTask的executeOnExecutor方法來并行執(zhí)行任務(wù)。
工作原理
@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實(shí)際上是一個(gè)串行的線程池烈涮,一個(gè)進(jìn)程中所有的AsyncTask全部在這個(gè)串行的線程池中排隊(duì)執(zhí)行朴肺。在executeOnExecutor方法中,AsyncTask的onPreExecute方法最先執(zhí)行坚洽,然后線程池開始執(zhí)行戈稿。
/**
* 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的排隊(duì)執(zhí)行過程:首先系統(tǒng)會(huì)把AsyncTask的Params參數(shù)封裝為FutureTask對(duì)象,F(xiàn)utureTask是一個(gè)并發(fā)類讶舰,在這里它充當(dāng)了Runnable的作用鞍盗。接著FutureTask交給SerialExecutor.execute方法處理。在execute方法中跳昼,futureTask首先被插入到任務(wù)隊(duì)列mTask中般甲,如果這個(gè)時(shí)候沒有正在活動(dòng)的任務(wù),則會(huì)調(diào)用scheduleNext方法執(zhí)行下一個(gè)AsyncTask任務(wù)鹅颊。當(dāng)一個(gè)AsyncTask任務(wù)執(zhí)行完后敷存,AsyncTask會(huì)繼續(xù)執(zhí)行其他任務(wù)直到所有的任務(wù)都被執(zhí)行為止。默認(rèn)情況下,AsyncTask是串行執(zhí)行的锚烦。
AsyncTask中有兩個(gè)線程池(SerialExecutor和THREAD_POOL_EXECUTOR)和一個(gè)Handler(InternalHandler)觅闽,其中線程池SerialExecutor用于任務(wù)的排隊(duì),而線程池THREAD_POOL_EXECUTOR用于真正地執(zhí)行任務(wù)涮俄,InternalHandler用于將執(zhí)行環(huán)境從線程池切換到主線程蛉拙。
在SerialExecutor中調(diào)用了FutureTask.run()。而在FutureTask.run方法中最后又會(huì)調(diào)用mWorker.call()方法彻亲,因此mWorker.call最終在線程池中執(zhí)行孕锄。
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;
}
##默認(rèn)情況下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苞尝,表示當(dāng)前任務(wù)已經(jīng)被調(diào)用過了畸肆,然后執(zhí)行AsyncTask.doInBackground方法,接著將其返回值傳遞給postResult方法野来。postResult方法會(huì)通過sHandler發(fā)送一個(gè)MESSAGE_POST_RESULT消息恼除。sHandler是一個(gè)靜態(tài)的Handler對(duì)象,為了能夠?qū)?zhí)行環(huán)境切換到主線程曼氛,sHandler必須在主線程中創(chuàng)建【其實(shí)按照現(xiàn)在的源碼來看豁辉,我的理解是不需要在主線程中聲明了,看下面代碼】舀患。
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;
}
}
默認(rèn)情況下AsyncTask持有的mHandler即為sHandler徽级,而目前默認(rèn)給sHandler的looper為主線程Looper,因此就算在子線程中初始化了AsyncTask聊浅,sHandler的handleMessage方法依舊在主線程中執(zhí)行餐抢。
sHandler收到MESSAGE_POST_RESULT消息后調(diào)用AsyncTask.finish()方法。
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
如果AsyncTask被取消執(zhí)行了低匙,那么回調(diào)mCancelled方法旷痕,否則調(diào)用onPostExecute方法。
自身理解
google的工程師在AsyncTask的構(gòu)造方法中加入了Looper參數(shù)顽冶,意味AsyncTask目前擁有更自由的定制化程度欺抗,我們可以給它傳入子線程下的Looper,同時(shí)當(dāng)前AsyncTask的onPreExecute方法和onPostExecute方法均會(huì)在當(dāng)前線程下回調(diào)而不是默認(rèn)的主線程强重。
二绞呈、HandlerThread
HandlerThread繼承了Thread,它是一種可以使用Handler的Thread间景,在run方法中通過Looper.prepare()創(chuàng)建消息隊(duì)列佃声,并通過Looper.loop()來開啟消息循環(huán)。
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方法中執(zhí)行一個(gè)耗時(shí)任務(wù)圾亏,而HandlerThread在內(nèi)部創(chuàng)建了消息隊(duì)列,外部需要通過Handler的消息方式來通知HandlerThread執(zhí)行一個(gè)具體的任務(wù)。
當(dāng)明確不需要再使用HandlerThread時(shí)召嘶,可以通過它的quit或者quitSafely方法來終止線程的執(zhí)行父晶。
三、IntentService
IntentService繼承自Service且自身是一個(gè)抽象類弄跌,可用于執(zhí)行后臺(tái)耗時(shí)的任務(wù),當(dāng)任務(wù)執(zhí)行后它會(huì)自動(dòng)停止尝苇。IntentService的優(yōu)先級(jí)比單純的線程高很多铛只,適合執(zhí)行一些高優(yōu)先級(jí)的后臺(tái)任務(wù)。
@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);
}
}
當(dāng)IntentService第一次啟動(dòng)時(shí)糠溜,會(huì)創(chuàng)建一個(gè)HandlerThread淳玩,通過它的Looper創(chuàng)建mServiceHandler。
啟動(dòng)IntentService時(shí)非竿,onStartCommand方法被調(diào)用蜕着,而在onStartCommand中又調(diào)用了onStart方法。
onStart方法中包裝一個(gè)Message對(duì)象红柱,將intent交給mServiceHandler處理承匣,最終由onHandleIntent()方法處理傳入的Itnent對(duì)象,這里的intent與外界通過startService(Intent intent)方法中傳遞的Intent對(duì)象內(nèi)容一致锤悄,通過這個(gè)Intent即可解析出外界啟動(dòng)IntentService時(shí)傳遞的參數(shù)韧骗,通過參數(shù)區(qū)分具體的后臺(tái)任務(wù)。
當(dāng)onHandleIntent方法執(zhí)行結(jié)束后零聚,IntentService會(huì)通過stopSelf(int startId)方法嘗試停止服務(wù)袍暴,這里之所以采用stopSelf(int startId)而不是stopSelf()停止服務(wù),因?yàn)閟topSelft()會(huì)立刻停止服務(wù)隶症,而這個(gè)時(shí)候可能還有其他消息未處理政模,stopSelf(int startId)會(huì)等待所有的消息處理完畢后才終止服務(wù)。一般來說蚂会,stopSelf(int startId)在嘗試停止服務(wù)之前會(huì)判斷最近啟動(dòng)服務(wù)的次數(shù)是否和staratId相等淋样,如果相等就立刻停止服務(wù),不相等則不停止服務(wù)颂龙。
由于IntentService內(nèi)部通過消息的方式向HandlerThread請(qǐng)求執(zhí)行任務(wù)习蓬,Handler中的Looper是順序處理消息的,這就意味著IntentService也是順序執(zhí)行后臺(tái)任務(wù)措嵌,當(dāng)有多個(gè)后臺(tái)任務(wù)同時(shí)純?cè)跁r(shí)躲叼,這些后臺(tái)任務(wù)會(huì)按照外界發(fā)起的順序排隊(duì)執(zhí)行。