一.HandlerThread的使用與原理解析
??HandlerThread繼承于Thread,所以它本質(zhì)就是個(gè)Thread。與普通Thread的差別就在于,它不僅建立了一個(gè)線(xiàn)程,并且創(chuàng)立了消息隊(duì)列,有自己的looper,可以讓我們?cè)谧约旱木€(xiàn)程中分發(fā)和處理消息,并對(duì)外提供自己這個(gè)Looper對(duì)象的get方法。
??HandlerThread自帶Looper使他可以通過(guò)消息隊(duì)列,來(lái)重復(fù)使用當(dāng)前線(xiàn)程,節(jié)省系統(tǒng)資源開(kāi)銷(xiāo)。這是它的優(yōu)點(diǎn)也是缺點(diǎn),每一個(gè)任務(wù)都將以隊(duì)列的方式逐個(gè)被執(zhí)行到,一旦隊(duì)列中有某個(gè)任務(wù)執(zhí)行時(shí)間過(guò)長(zhǎng),那么就會(huì)導(dǎo)致后續(xù)的任務(wù)都會(huì)被延遲處理。
1.HandlerThread使用步驟
第一步:創(chuàng)建HandlerThread實(shí)例對(duì)象
HandlerThread handlerThread = new HandlerThread("myThread");
第二步:啟動(dòng)HandlerThread線(xiàn)程
handlerThread.start();
第三步:構(gòu)建循環(huán)消息處理機(jī)制
private Handler.Callback mSubCallback = new Handler.Callback() {
//該接口的實(shí)現(xiàn)就是處理異步耗時(shí)任務(wù)的,因此該方法執(zhí)行在子線(xiàn)程中
@Override
public boolean handleMessage(Message msg) {
//doSomething 處理異步耗時(shí)任務(wù)的
mUIHandler.sendMessage(msg1); //向UI線(xiàn)程發(fā)送消息,用于更新UI等操作
}
};
第四步:構(gòu)建子線(xiàn)程中的Handler:
//由于這里已經(jīng)獲取了workHandle.getLooper(),因此這個(gè)Handler是在HandlerThread線(xiàn)程也就是子線(xiàn)程中
childHandler = new Handler(handlerThread.getLooper(), mSubCallback);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//發(fā)送異步耗時(shí)任務(wù)到HandlerThread中,也就是上面的mSubCallback中
childHandler.sendMessage(msg);
}
});
第五步:構(gòu)建UI線(xiàn)程Handler處理消息(如果需要更新UI的話(huà)有這一步)
private Handler mUIHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
//在UI線(xiàn)程中做的事情,比如設(shè)置圖片什么的
}
};
2.HandlerThread的實(shí)現(xiàn)原理
??HandlerThread的實(shí)現(xiàn)原理比較簡(jiǎn)單,源碼也比較少(只有150行代碼),首先它是繼承自Thread類(lèi)的:
public class HandlerThread extends Thread {
因此它完全可以當(dāng)一個(gè)線(xiàn)程來(lái)使用,就像上面我們說(shuō)的:new HandlerTread().start()這樣,但是!!!——我們之前在Android中的消息機(jī)制——Looper、Handler、MessageQueue與Message這篇文章中說(shuō)過(guò),在子線(xiàn)程中創(chuàng)建一個(gè)Handler,需要手動(dòng)創(chuàng)建Looper,即先Looper.parpare(),完了再Looper.loop()
這樣,我們來(lái)看看HandlerThread中的run方法:
@Override
public void run() {
mTid = Process.myTid(); //獲得當(dāng)前線(xiàn)程的id
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
//發(fā)出通知,當(dāng)前線(xiàn)程已經(jīng)創(chuàng)建mLooper對(duì)象成功,這里主要是通知getLooper方法中的wait
notifyAll();
}
//設(shè)置當(dāng)前線(xiàn)程的優(yōu)先級(jí)
Process.setThreadPriority(mPriority);
//該方法實(shí)現(xiàn)體是空的,子類(lèi)可以實(shí)現(xiàn)該方法,作用就是在線(xiàn)程循環(huán)之前做一些準(zhǔn)備工作,當(dāng)然子類(lèi)也可以不實(shí)現(xiàn)。
onLooperPrepared();
Looper.loop();
mTid = -1;
}
可以看到,這個(gè)run方法里邊寫(xiě)死了,先Looper.prepare()然后Looper.loop(),也即是說(shuō),我們的HandlerThread這個(gè)特殊的“線(xiàn)程”是再帶Looper的,因此——我們不能再主線(xiàn)程使用它,畢竟主線(xiàn)程是自帶MainLooper的,一個(gè)線(xiàn)程只能有一個(gè)Looper,否則就會(huì)拋出異常。
??這里我們說(shuō)一下,為什么要看這個(gè)run()方法,之前我們?cè)?a href="http://www.lxweimin.com/p/72194931f805" target="_blank">Android中的線(xiàn)程形態(tài)(一)(進(jìn)程/線(xiàn)程/線(xiàn)程池)中有講過(guò),Thread工作的時(shí)候,不論哪種實(shí)現(xiàn)方法,我們都必須重寫(xiě)這個(gè)類(lèi)的run()方法,在其中寫(xiě)我們自己要做的事情。可以看到,HandlerThread類(lèi)的run()方法已經(jīng)給我們寫(xiě)死了,這就注定我們只能將它用在子線(xiàn)程中。
??我們?cè)賮?lái)看看HandelerThread類(lèi)的額另一個(gè)重要的方法——getLooper():
//該方法主要作用是獲得當(dāng)前HandlerThread線(xiàn)程中的mLooper對(duì)象
public Looper getLooper() {
if (!isAlive()) { //如果線(xiàn)程不是活動(dòng)的,則直接返回null
return null;
}
// If the thread has been started, wait until the looper has been created.
//如果線(xiàn)程已經(jīng)啟動(dòng),但是Looper還未創(chuàng)建的話(huà),就等待,直到Looper創(chuàng)建成功
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
//這里會(huì)調(diào)用wait方法去等待,當(dāng)run方法中的notifyAll方法調(diào)用之后
//通知當(dāng)前線(xiàn)程的wait方法等待結(jié)束,跳出循環(huán),獲得mLooper對(duì)象的值。
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
OK,看到這里,結(jié)合上面的HandelrThread使用步驟,我們需要總結(jié)一下:
- HandelrThread是一個(gè)自帶Looper的線(xiàn)程,因此只能作為子線(xiàn)程使用
- HandlerThread必須配合Handler使用,HandlerThread線(xiàn)程中做具體事情,必須要在Handler的callback接口中進(jìn)行,他自己的run方法被寫(xiě)死了。
- 子線(xiàn)程中的Handler與HandlerThread的聯(lián)系是通過(guò)
childHandler = new Handler(handlerThread.getLooper(), mSubCallback);
這句來(lái)進(jìn)行的,也就是你說(shuō),childHandler獲得HandlerThread線(xiàn)程的Looper,這樣,他們兩個(gè)就在同一陣營(yíng)了。這也就是在創(chuàng)建Handler作為HandlerThread線(xiàn)程消息執(zhí)行者,必須在調(diào)用start()方法之后的原因——HandlerThread.start()之后,run()方法才能跑起來(lái),Looper才能得以創(chuàng)建,handlerThread.getLooper()
才不會(huì)出錯(cuò)。
二.IntentService的使用與實(shí)現(xiàn)原理
??HandlerThread在Android中的一個(gè)具體的應(yīng)用就是IntentService。IntentService是繼承于Service并處理異步請(qǐng)求的一個(gè)類(lèi)。注意這句話(huà)——“繼承于Service”和“處理異步請(qǐng)求”。“繼承于Service”表示他是一個(gè)服務(wù),我們知道Service是存在于主線(xiàn)程的,它之中不能存在耗時(shí)操作,否則的話(huà)回應(yīng)起ANR,因此便有了IntentService——這個(gè)封裝了HandlerThread和Handler的特殊Service。
1.IntentService的使用
第一步:創(chuàng)建一個(gè)繼承IntentService類(lèi)的子類(lèi)
首先,通過(guò)源碼我們知道,IntentService是一個(gè)繼承自Service類(lèi)的抽象類(lèi),因此我們必須創(chuàng)建一個(gè)繼承它的子類(lèi)才能實(shí)現(xiàn)相關(guān)功能:
public class MyIntentService extends IntentService {
public ServiceUpdate() {
// 注意構(gòu)造函數(shù)參數(shù)為空,這個(gè)myIntentService字符串就是IntentService中工作線(xiàn)程的名字
super("myIntentService");
}
//打印生命周期
@Override
public void onCreate() {
Log.i("myIntentService", "onCreate");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("myIntentService", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onStart(Intent intent, int startId) {
Log.i("myIntentService", "onStart");
super.onStart(intent, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.i("myIntentService", "onBind");
return super.onBind(intent);
}
//重寫(xiě)onHandleIntent方法,在該方法中進(jìn)行我們的各種事務(wù)處理
@Override
protected void onHandleIntent(Intent intent) {
//一般Intent是從Activity發(fā)過(guò)來(lái)的,攜帶識(shí)別參數(shù),根據(jù)參數(shù)不同執(zhí)行不同的任務(wù)
String taskName = intent.getExtras().getString("taskName");
switch (taskName) {
case "task1":
Log.i("myIntentService", "task1");
break;
case "task2":
Log.i("myIntentService", "task2");
break;
default:
break;
}
}
@Override
public void onDestroy() {
Log.i("myIntentService", "onDestroy");
super.onDestroy();
}
}
第二步:在Activity中開(kāi)啟服務(wù):
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
......
//同一服務(wù)只會(huì)開(kāi)啟一個(gè)工作線(xiàn)程,在onHandleIntent函數(shù)里依次處理intent請(qǐng)求。
Intent intent1 = new Intent(this,MyIntentService.class);
Bundle bundle = new Bundle();
bundle.putString("taskName", "task1");
intent1.putExtras(bundle);
startService(intent1);
Intent intent2 = new Intent(this,MyIntentService.class);
Bundle bundle2 = new Bundle();
bundle2.putString("taskName", "task2");
intent2.putExtras(bundle2);
startService(intent2);
}
}
第三步:在 Manifest 中注冊(cè)服務(wù)
<service android:name=".service.MyIntentService"/>
上述過(guò)程中我們啟動(dòng)了兩個(gè)IntentService服務(wù),打印出來(lái)生命周期為:onCreate -> onStartCommand -> onStart -> onStartCommand -> onStart -> task1 -> task2 -> onDestroy,OnBinder沒(méi)有執(zhí)行。
??從結(jié)果可以看到,onCreate 方法只執(zhí)行了一次,而 onStartCommand 和 onStart 方法執(zhí)行了兩次,開(kāi)啟了兩個(gè) 工作線(xiàn)程(Work Thread),這就證實(shí)了之前所說(shuō)的,啟動(dòng)多次,但I(xiàn)ntentService 的實(shí)例只有一個(gè),這跟傳統(tǒng)的Service 是一樣的。
2.IntentServic源碼分析
??IntentService繼承Service類(lèi)之后,整體的源碼也就165行,跟HandlerThread差不多,我們先來(lái)看看它的實(shí)例變量:
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper; //服務(wù)所在線(xiàn)程的Looper
private volatile ServiceHandler mServiceHandler; //構(gòu)建一個(gè)服務(wù)中的Handler
private String mName; //服務(wù)所在線(xiàn)程的名字
private boolean mRedelivery;
1).IntentService的構(gòu)造方法
上面加了注釋的三個(gè)變量較為重要,我們待會(huì)會(huì)一步步分析。接下來(lái)我們看看他的構(gòu)造方法:
public IntentService(String name) {
super();
mName = name;
}
可以看到,上線(xiàn)例子中我們得
public ServiceUpdate() {
super("myIntentService");
}
其中“myIntentService”實(shí)際會(huì)上傳到父類(lèi)IntentService的構(gòu)造方法中,也就是IntentService所在線(xiàn)程的線(xiàn)程名字,IntentService構(gòu)造方法中的super();
又會(huì)進(jìn)一步調(diào)用Service類(lèi)中的構(gòu)造函數(shù):
public Service() {
super(null);
}
再網(wǎng)上,就到ContextWrapper類(lèi)里邊去了。如果我們看過(guò)Activity的源碼的話(huà)就會(huì)知道,Activity也是繼承自ContextWrapper類(lèi)的,而ContextWrapper類(lèi)繼承自Context!也就說(shuō),Service和Activity實(shí)際上都是一個(gè)Context!ContextWrapper有一個(gè)比較特殊的地方是,他的實(shí)例化的地方是在ActivityThread中由系統(tǒng)完成的,我們無(wú)權(quán)插手。因此,在StartService或者StartActivity的時(shí)候,系統(tǒng)就會(huì)自動(dòng)幫我們實(shí)例化這兩個(gè)組件。這樣,Service的構(gòu)造方法為空也就很好解釋了。
2).OnCreat()
??看上面的生命周期流程圖我們知道,IntentService第一步指定的onCreat方法:
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
首先,super.onCreate();
,這個(gè)我們看到Service的onCreat()方法是空的,所以不管,接著看。HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
看到了吧,這里重量級(jí)人物——HandlerThread出場(chǎng)了,新建了一個(gè)HandlerThread實(shí)例,上面我們說(shuō)過(guò)HandlerThread()的構(gòu)造方法傳進(jìn)去的是HandlerThread所在線(xiàn)程的名字,然后thread.start();
,嗯,非常符合我們上半片文章講的HandlerThread使用流程。
??mServiceLooper = thread.getLooper();
這里通過(guò)mServiceLooper獲取到HandlerThread線(xiàn)程的Looper。然后mServiceHandler = new ServiceHandler(mServiceLooper);
,我們接著看源碼:
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);
}
}
可以看到,ServiceHandler是IntentService類(lèi)的一個(gè)內(nèi)部類(lèi),并且繼承自Handler,重寫(xiě)了handleMessage方法。很顯然,這個(gè)類(lèi)是用來(lái)處理startService(intent);
傳遞來(lái)的消息的。這個(gè)消息處理的過(guò)程分為兩步,第一調(diào)用onHandleIntent((Intent)msg.obj);
方法;第二步stopSelf(msg.arg1);
消息處理完后自動(dòng)終止服務(wù)。所以我們接著而看onHandleIntent((Intent)msg.obj);
:
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
呦呵?這是一個(gè)抽象方法,抽象類(lèi)中的抽象方法意味著我們需要在子類(lèi)中重寫(xiě)這個(gè)方法,也就是說(shuō),這個(gè)方法才是我們處理消息的地方。可以看到,這個(gè)方法上面加了注解,是位于工作線(xiàn)程(子線(xiàn)程)中的。
3).onStartCommand()/onStart()
??好了,OnCreat()方法終于執(zhí)行完了,onStartCommand()方法,它和onStart()方法實(shí)際上是連在一起的:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
直接看onStart():
@Override
public void onStart(Intent intent, int startId) {
//Service 啟動(dòng)后直接就向 mServiceHandler 發(fā)送消息,則馬上就會(huì)執(zhí)行 handleMessage方法
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
這個(gè)方法中,mServiceHandler這個(gè)Handler的子類(lèi),調(diào)用了obtainMessage()方法,該方法實(shí)際上上到Handler類(lèi)中調(diào)用的是:
public final Message obtainMessage(){
return Message.obtain(this);
}
這個(gè)方法中,Message.obtain(this);
這個(gè)方法我們復(fù)習(xí)一下,實(shí)際上就是Handler從消息池中取出一個(gè)消息,避免Message類(lèi)重復(fù)創(chuàng)建的一個(gè)方法。回到IntentSerice的onStart()方法中,Message msg = mServiceHandler.obtainMessage();
,這句就是獲取一個(gè)Message對(duì)象,然后mServiceHandler.sendMessage(msg);
通過(guò)Handler發(fā)送消息,添加到Looper中的MessageQuenue隊(duì)列中。
4).onDestroy()
@Override
public void onDestroy() {
mServiceLooper.quit();
}
安全退出Looper()
3.IntentService中的一些坑
1).為什么不建議通過(guò) bindService() 啟動(dòng) IntentService?
@Override
public IBinder onBind(Intent intent) {
return null;
}
??IntentService 源碼中的 onBind() 默認(rèn)返回 null;不適合 bindService() 啟動(dòng)服務(wù),如果你執(zhí)意要 bindService() 來(lái)啟動(dòng) IntentService,可能因?yàn)槟阆胪ㄟ^(guò) Binder 或 Messenger 使得 IntentService 和 Activity 可以通信,這樣那么 onHandleIntent() 不會(huì)被回調(diào),相當(dāng)于在你使用 Service 而不是 IntentService。
2).為什么多次啟動(dòng) IntentService 會(huì)順序執(zhí)行事件,停止服務(wù)后,后續(xù)的事件得不到執(zhí)行?
??IntentService 中使用的 Handler、Looper、MessageQueue 機(jī)制把消息發(fā)送到線(xiàn)程中去執(zhí)行的,所以多次啟動(dòng) IntentService 不會(huì)重新創(chuàng)建新的服務(wù)和新的線(xiàn)程,只是把消息加入消息隊(duì)列中等待執(zhí)行,而如果服務(wù)停止,會(huì)清除消息隊(duì)列中的消息,后續(xù)的事件得不到執(zhí)行。
站在巨人的肩膀上摘蘋(píng)果:
IntentService 示例與詳解
Service 和 IntentService 的區(qū)別等