Android進階9:IntentService的妙用

原來模式

咱們知道Service是運行在主線程裏的,所以,若是在服務裏面執行耗時代碼操做,咱們須要開啓一個子線程去處理這些代碼。好比咱們能夠在onStartCommand方法裏面去開啓子線程來處理耗時代碼。java

public int onStartCommand(Intent intent, int flags, int startId) {
         Thread thread = new Thread(){
            @Override
            public void run() {
                /**
                 * 耗時的代碼在子線程裏面寫
                 */

            }
          };
        thread.start();
        return super.onStartCommand(intent, flags, startId);
    }
複製代碼

可是,咱們都知道,服務一旦啓動,就會一直運行下去,必須調用stopService()或者stopSelf()方法才能讓服務中止下來。因此,咱們來修改一下run方法android

public void run() {
         /**
           * 耗時的代碼在子線程裏面寫
           */

        stopSelf();

     }
    }
複製代碼

就這樣,咱們很容易的就在服務裏面開啓了一個線程,而後在代碼最後面加上stopSelf();這樣就能夠在代碼運行結束的時候,結束服務了。可是這樣對於咱們開發者來講,是否是有些麻煩呢,確實有點麻煩,好比你有時候忘記了開啓線程呢?或者忘記了調用stopSelf()?web

因此,谷歌給咱們一個很好的類,經過這個類咱們就能夠不用管這些東西,由於這個類已經幫咱們實現了在子線程中操做代碼了。同時,但子線程代碼執行完畢,這個服務會自動銷燬,不用再佔用內存資源。因此,咱們經過這個類,就能夠不用去開啓線程,也不用去銷燬這個服務。由於,這個類都幫咱們處理好了。這個類就是IntentService。這個類的使用和Service大同小異,可是比Service更加省心,更加方便。下面咱們直接看代碼吧,我習慣在代碼中講解。app

IntentService源碼

/**
 * IntentService是一個以{@linkService}的爲基類來處理異步請求的類
 * 客戶端發送請求經過{@link android.content.Context *#startService(Intent)}調用;
 * 該服務根據須要啓動,使用worker線程依次處理每一個Intent線程,並在run工做完成時自行中止本service。
 *
 * <p>這種「工做隊列處理器」模式一般用於卸載任務
 *來自應用程序的主線程。 IntentService類存在於
 *簡化這種模式並處理機制。要使用它,請擴展
 * IntentService並實現{@link #onHandleIntent(Intent)}。 IntentService
 * 將接收Intents,啓動工做線程,並中止服務
 *合適。
 *
 * <p>全部請求都在一個工做線程上處理 - 它們能夠做爲
 *儘量長(而且不會阻止應用程序的主循環),可是
 *一次只能處理一個請求。
 *
 */

public abstract class IntentService extends Service {

    //開啓線程的Looper
    private volatile Looper mServiceLooper;
    //用於發送和處理消息的handler
    private volatile ServiceHandler mServiceHandler;
    //子線程的名稱
    private String mName;
    //是否可重複發送
    private boolean mRedelivery;


    //處理消息handler的實現
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            //子線程

            //抽象方法 留給子類去重寫
            onHandleIntent((Intent)msg.obj);
            // 子線程任務執行完了,中止本service
            stopSelf(msg.arg1);
        }
    }

    /**
     * 構造函數
     * @param name worker線程的名字 對調試有用
     */

    public IntentService(String name) {
        super();
        mName = name;
    }

    /**
     * 
     * Sets intent redelivery preferences.  Usually called from the constructor
     * with your preferred semantics.
     * 設置intent重發偏好,一般在構造函數調用
     *
     *
     * 若是設置是true,{@link #onStartCommand(Intent, int, int)} 將返回{@link Service#START_REDELIVER_INTENT}
     * 所以,若是這個進程在onHandleIntent返回以前死掉了,那麼進程將會被重啓,而且發送此intent
     * 若是多個intents被髮送,只有最近的一個會被確保從新發送
     *
     * 若是設置爲false,{@link #onStartCommand(Intent, int, int)} 將返回{@link Service#START_NOT_STICKY}
     * 若是這個進程死掉了,那麼這個intent就死掉了
     *
     */

    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {

        super.onCreate();

        //使用HandlerThread開啓一個線程,併產生looper和消息隊列
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        //獲取上述子線程的looper
        mServiceLooper = thread.getLooper();
        //初始化 handler
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        //onstart時發送一個消息給handle

        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);

        //是否可重複發送
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

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

    /**
     * Unless you provide binding for your service, you don't need to implement this
     * method, because the default implementation returns null. 
     * @see android.app.Service#onBind
     */

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

    /**

     * 這個方法在子線程中執行,一次只能執行一個事件,
     */

    @WorkerThread
    protected abstract void onHandleIntent(Intent intent);
}
複製代碼

總結:使用IntentServices是使用Service+ HandlerThread的方式,不少狀況下咱們能夠使用HandlerThread+ handler 來進行線程執行和handler分發消息。less

相關文章
相關標籤/搜索