源碼探索系列8---IntentService

我們知道,我們的Service如果要執行一些耗時的操作,需要開單獨的線程去幹活,而IntentService卻不用,
在他的onHandleIntent函數裏面我們可以執行耗時操作,啊,到底神奇在哪裏了呢?
讓我們去看看他的源碼,背後到底做了什麼好事情!

起航 — IntentService

API:23

public abstract class IntentService extends Service 

我們的IntentService是一個繼承Service的抽象類,那關於他的啓動,停止等就和Service一樣,前一篇就解釋過了,我們現在就不說了。整個類也就164行,不大,還不夠AMS裏面一個函數的一半長度,哈,我們從他的OnCreate函數開始吧

@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);
}

我們看到他開了一個子線程和Handler。這裏我們可以猜測了,之所以在我們的onHandleIntent很可能是因爲他們兩個!
讓我們繼續看下去

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

@Override
public void onStart(Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

好了,我們看到了線索了,發送過來的消息,通過onStartCommand()跑到了onStart,他裏面調用了Handler去發送一個包含我們的Intent的消息。讓我們去看下這個消息背後被怎麼處理

@Override
public void handleMessage(Message msg) {
    onHandleIntent((Intent)msg.obj);
    stopSelf(msg.arg1);
}

我們看到他就直接調用我們的onHandleIntent(),讓我們去處理髮送過來的Intent。
處理完後調用stopSelf(int id);,這個函數需要解釋下,他和我們的stopSelf()是有區別的,前者是判斷下看是否還有沒處理的消息,有就繼續幹活,沒有才結束,後者就不管啦,死就死的。

後記

這裏有些需要補充的:

  1. 排隊
    我們看到,這個IntentService是藉助消息隊列實現的,這種單線程,排隊的任務隊列,每次只執行一個,後面來的就需要等前面一個做完。
    這點可能有時不適合我們的實際需求情況,我們可能還想一次幹多點,這時候還是我們自己在Service裏面做吧!
    但他有些好的,就是他處理完就會去調用 stopSelf(msg.arg1);

  2. WakeLock
    不知道你有沒注意到,在他的OnCreate函數他注視裏面有個todo的內容

    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.

    關於這個wakelock,可以補充點內容在這裏,因爲這篇突然好短,哈哈,都不習慣了,所以使勁加點內容
    他的作用可以讓屏幕保持喚醒,不過得先聲明下權限

    <uses-permission android:name="android.permission.WAKE_LOCK" />

    曾經使用他的一個情景就是在做IM功能的時候,在做那個聲音的功能的時候,需要用他來保持喚醒。

    wakeLock = ((PowerManager) getSystemService(Context.POWER_SERVICE)).
                newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "demo");
    
    wakeLock.acquire(); //設置保持喚醒
    
    ...
    
    wakeLock.release(); //解除保持喚醒
    

    另外我們平時使用手機看電影的時候,也會遇到過,要保持屏幕常量嘛。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章