IntentService從源碼解析

子線程的生命週期就是run方法結束了就結束了,這個我要說的一點就是HandlThread類,這裏是由於quene.next()一直監聽着消息隊列,處於堵塞狀態,所以這個線程是創建了就一直存在的。案例說安卓的主線程run方法執行完了也就該退出,由於安卓的主線程是一個特殊的線程所以一直存在。
這裏寫圖片描述
這裏寫圖片描述
下面我們看下曾經寫過的一個主線程給子線程的發送的案例
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(MainActivity.this,msg.toString(), Toast.LENGTH_LONG).show();
}
};
Looper.loop();

        }
    });
    thread.start();

}
public void click(View view){
    handler.obtainMessage(2, "主線程給子線程發送消息").sendToTarget();
}

這裏的子線程就是通過looper. loop()一直一直監聽消息隊列處於堵塞狀態,所以這個線程也是一直存在的,所以導致內存泄漏的問題,一般來說,我們不不能夠這樣子用的,除非我們需要某個線程一直存在從消息隊列裏拿東西,那樣我們會使用這種做法,有個HandlerThread類大概就是使用了這一原理。

下面我們來通過源碼追究一下HandlerThread是個什麼東西?
HanlderThread其實就是一個Thread,繼承了Thread的一個類,一般線程都是run方法執行結束的話就應該結束了,但是HandlerThread內部通過創建Looper.Prepared()創建消息隊列,通過Looper.Loop()開啓消息循環,由於消息循環是一個堵塞的死循環,所以這個消息隊列一直存在着,可以執行耗時的任務,由於這是個無限循環的,所以我們明確的想要關閉的話,可以使用quit,或者quitSafely();
下面我們追源碼看看這個quit都做了什麼?
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
追進去發現
quit方法
public void quit() {
mQueue.quit(false);
}
quitSafely方法
public void quitSafely() {
mQueue.quit(true);
}
以上兩個方法都是調用了 MessageQueue 的quit方法,下面我們看下MessageQueen中的兩個方法差別在哪?
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new RuntimeException(“Main thread not allowed to quit.”);
}
synchronized (this) {
if (mQuiting) {
return;
}
mQuiting = true;
if (safe) {
removeAllFutureMessagesLocked();//清空延遲消息,將消息池中的非延遲消息派發出去由handler處理
} else {
removeAllMessagesLocked();//清空裏面所有的消息,不論延遲還是非延遲的
}
}
nativeWake(mPtr);
}
quitSafely相比quit方法的安全之處在於在清空消息之前會派發所有的非延遲消息。
無論是調用了quit方法還是quitSafely方法只會,Looper就不再接收新的消息。即在調用了Looper的quit或quitSafely方法之後,消息循環就終結了,這時候再通過Handler調用sendMessage或post等方法發送消息時均返回false,表示消息沒有成功放入消息隊列MessageQueue中,因爲消息隊列已經退出了。

這麼就是說在調用quit方法之後消息隊列關閉了,所以這樣就不存在消息堵塞機制了,那麼線程的run方法就可以結束啦。

當我們開啓一個Intentservice的時候會傳入一個intent值。
}
public void click3(View v){

    Intent service=new Intent(this, Myintentservice.class);
    service.putExtra("a", "第三次開啓intentService");
    startService(service);
}

其實intentService的核心就是在於在他的Oncreate()方法中我們創建了一個HandlerHtread,然後把這個Thread傳進一個ServiceHandler 構造方法裏面,這樣這個ServiceHandler 發送的消息都是在這個Handler中執行的。onstart()方法恰恰就是把開啓service傳進來的intent值發送到ServiceHandler中

IntentService內部類
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是把onHandleIntent抽象出去讓子類去實現的
protected abstract void onHandleIntent(Intent intent);

看到這個stopSelf方法了嗎,這個就是當onHandleIntent方法執行完了以後IntentService會通過stopSelf(int id)終止服務,爲什麼用stopSelf()是因爲這個是立刻終止服務,而帶參數的這個是待消息執行完才終止服務。

我們看看oncreate,onstart
@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 void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}

由於Handler中Loop中的MessageQueen中的任務都是按照順序執行的,所以intentService中的任務也是按照順序執行的。

發佈了35 篇原創文章 · 獲贊 14 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章