十、IntentService解析

intentService是Android里面的一個封裝類,繼承自Service,用于異步請求,實現(xiàn)多線程。
工作流程:


intentService工作流程

如果啟動IntentService多次,那么每個耗時操作那么每個耗時操作則以隊列的形式在intentService的onHandleIntent回調(diào)方法中依次執(zhí)行,執(zhí)行完自動結(jié)束。

1.實現(xiàn)步驟

    1. 定義IntentService的子類:傳入線程名稱、復(fù)寫onHandleIntent方法。
  • 2.在Manifest文件中注冊
  • 3.在Activity中啟動Service服務(wù)。

2.具體實例

  1. 定義IntentService的子類
public class MyIntentService extends IntentService {
    /**
     * 構(gòu)造函數(shù),傳入的參數(shù)是工作線程的名稱
     * @param
     */
    public MyIntentService() {
        super("wyw");
    }

   //實現(xiàn)耗時任務(wù)
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        //根據(jù)intent的不同,進行不同的事務(wù)處理
        String taskName = intent.getExtras().getString("taksName");
        switch (taskName){
            case "taks1":
                Log.i("MyIntentService", "task1");
                break;
            case "task2":
                Log.i("MyIntentService", "task2");
                break;
            case "task3":
                Log.i("MyIntentService", "task3");
                break;
        }
    }
}
  1. 在manifest文件中注冊:
<service android:name=".MyIntentService">
            <intent-filter>
                <action android:name="com.wyw.service"/>
            </intent-filter>
 </service>
  1. 在activity中啟動
        Intent intent  = new Intent("com.wyw.service");
        Bundle bundle = new Bundle();
        bundle.putString("taskName","task1");
        intent.putExtras(bundle);
        startService(intent);

        Intent intent2  = new Intent("com.wyw.service");
        Bundle bundle2 = new Bundle();
        bundle.putString("taskName","task2");
        intent2.putExtras(bundle2);
        startService(intent2);
        startService(intent); //多次啟動

運行結(jié)果


多次啟動IntentService結(jié)果

3.源碼分析

  • IntentService如何單獨開啟一個新的工作線程?
//IntentService onCreate()方法
 @Override
    public void onCreate() {
   //HandlerThread繼承自Thread,內(nèi)部封裝了Looper
   //通過實例化HandlerThread新建線程并啟動
   //所以使用IntentService時不需要額外新建線程
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
    //獲得工作線程的Looper,并維護自己的工作隊列
        mServiceLooper = thread.getLooper();
    //新建Hanler屬于工作線程
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
      //IntentService的handleMessage方法把接收的消息交給onHandleIntent()處理。
      //onHandleIntent()是一個抽象方法,使用時需要重寫的方法。
        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }
  • IntentService如何通過onStartCommand()傳遞給服務(wù)intent被依次插入到工作隊列中?
    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        //把intent參數(shù)包裝到message的obj中,然后發(fā)送消息,即添加到消息隊列中
        //這里的intent就是啟動服務(wù)時startService(Intent)的intent。
        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();
    }
  • 總結(jié)
    從源碼可以看出,IntentService本質(zhì)是采用Handler & HandlerThread方式:
    1. 通過HandlerThread單獨開啟一個名為IntentService 的線程。
    2. 創(chuàng)建一個名叫ServiceHandler的Handler。
    3. 把內(nèi)部Handler與HandlerThread所對應(yīng)的子線程進行綁定
    4. 通過onStartCommand()傳遞給服務(wù)intent,依次插入到工作隊列中,并逐個發(fā)送給onHandleIntent()。
    5. 通過onHandleIntent()來依次處理所有Intent請求對象所對應(yīng)的任務(wù)。

因此我們通過復(fù)寫onHandleIntent(),再根據(jù)Intent的不同進行不同進行不同的現(xiàn)場操作就可以了。
注意:工作任務(wù)隊列是順序執(zhí)行的。

如果一個任務(wù)正在IntentService中執(zhí)行,此時你再發(fā)送一個新的任務(wù)請求,這個新的任務(wù)會一直等待直到前面一個任務(wù)執(zhí)行完畢才開始執(zhí)行。

原因:

  1. 由于onCreate()方法只會調(diào)用一次,所以只會創(chuàng)建一個工作線程;
  2. 當(dāng)多次調(diào)用startService(Intent)時(onStartCommand也會調(diào)用多次)其實并會創(chuàng)建新的工作線程,只是把消息加入消息隊列中等待執(zhí)行,所以多次啟動IntentService會按照順序執(zhí)行。
  3. 如果服務(wù)停止,會清除消息隊列中的消息,后續(xù)的事件得不到執(zhí)行。

4.使用場景

  • 線程任務(wù)需要順序、在后臺執(zhí)行的使用場景(離線下載)
  • 由于所有的任務(wù)都在同一個Thread looper里面來做,所以不符合多個數(shù)據(jù)同時請求的場景。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容