1. 程式人生 > >Android IntentService 原始碼分析

Android IntentService 原始碼分析

IntentService也算比較常用的一個元件,所以有必要增加對它的瞭解。
首先看看原始碼

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    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); } } /** * Creates an IntentService. Invoked by your subclass's constructor. * * @param name Used to name the worker thread, important only for debugging. */
public IntentService(String name) { super(); mName = name; } public void setIntentRedelivery(boolean enabled) { mRedelivery = enabled; } @Override public void onCreate() { super.onCreate(); HandlerThread thread = new HandlerThread
("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public void onStart(@Nullable Intent intent, int startId) { Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); } @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 onDestroy() { mServiceLooper.quit(); } @Override @Nullable public IBinder onBind(Intent intent) { return null; } @WorkerThread protected abstract void onHandleIntent(@Nullable Intent intent);

IntentService 四個成員變數
volatile大家都懂的,記憶體可見性,禁止編譯器優化程式碼重排。

    private volatile Looper mServiceLooper; //子執行緒的looper
    private volatile ServiceHandler mServiceHandler; //靜態內部類,繼承handler
    private String mName;//作為工作執行緒名
    private boolean mRedelivery;//是否重投遞

介紹下方法

  @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);

入參是intent,在子執行緒種執行,也就是大家要做的耗時操作都在這裡做,本身是個抽象方法,需要我們實現的。

 @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

並沒有bindservice 這種操作,直接返回 null;

 @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

銷燬時,退出looper迴圈,資源回收

   @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }
  public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

值得注意的是在onStartCommand中返回值,常用的返回值有:START_NOT_STICKY、START_SICKY和START_REDELIVER_INTENT,這三個都是靜態常理值。

START_NOT_STICKY:

表示當Service執行的程序被Android系統強制殺掉之後,不會重新建立該Service,如果想重新例項化該Service,就必須重新呼叫startService來啟動。
使用場景:表示當Service在執行工作中被中斷幾次無關緊要或者對Android記憶體緊張的情況下需要被殺掉且不會立即重新建立這種行為也可接受的話,這是可以在onStartCommand返回值中設定該值。如在Service中定時從伺服器中獲取最新資料

START_STICKY:

表示Service執行的程序被Android系統強制殺掉之後,Android系統會將該Service依然設定為started狀態(即執行狀態),但是不再儲存onStartCommand方法傳入的intent物件,然後Android系統會嘗試再次重新建立該Service,並執行onStartCommand回撥方法,這時onStartCommand回撥方法的Intent引數為null,也就是onStartCommand方法雖然會執行但是獲取不到intent資訊。
使用場景:如果你的Service可以在任意時刻執行或結束都沒什麼問題,而且不需要intent資訊,那麼就可以在onStartCommand方法中返回START_STICKY,比如一個用來播放背景音樂功能的Service就適合返回該值。

START_REDELIVER_INTENT:

表示Service執行的程序被Android系統強制殺掉之後,與返回START_STICKY的情況類似,Android系統會將再次重新建立該Service,並執行onStartCommand回撥方法,但是不同的是,Android系統會再次將Service在被殺掉之前最後一次傳入onStartCommand方法中的Intent再次保留下來並再次傳入到重新建立後的Service的onStartCommand方法中,這樣我們就能讀取到intent引數。

     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, 這個是子執行緒的handler,覆寫 handleMessage ,做了兩件事,一個呼叫我們實現的onHandleIntent 執行我們的耗時操作,之後
stopSelf(msg.arg1);檢查是不是最後一個任務ID,如果是就stopself.

     @Override
    public void onCreate() {
  
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

建立HandlerThread 並啟動,取出looper關連mServiceHandler。

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


onStartCommand 呼叫onStart ,onStart 中建立訊息用mServiceHandler.sendMessage傳送到子執行緒的訊息佇列,在子執行緒的looper中呼叫mServiceHandler 的 handleMessage處理這個訊息。handler looper message機制已經被說爛了,這裡就不詳談。

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    

    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    /**
     * Call back method that can be explicitly overridden if needed to execute some
     * setup before Looper loops.
     */
    protected void onLooperPrepared() {
    }

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


    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }


    public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

    /**
     * Returns the identifier of this thread. See Process.myTid().
     */
    public int getThreadId() {
        return mTid;
    }
}

官方實現的一個子執行緒用handler looper message機制。也簡單易懂。