Android面試收集錄9 IntentService詳解

來源:互聯網
上載者:User

標籤:pat   amp   etl   extra   工作   self   非同步請求   put   注意事項   

一、 定義

IntentService是Android裡面的一個封裝類,繼承自四大組件之一的Service。

 

 

二、作用

處理非同步請求,實現多線程

 

 

三、 工作流程

注意:若啟動IntentService 多次,那麼每個耗時操作則以隊列的方式在 IntentService的onHandleIntent回調方法中依次執行,執行完自動結束。

 

 

四、實現步驟
  • 步驟1:定義IntentService的子類:傳入線程名稱、複寫onHandleIntent()方法
  • 步驟2:在Manifest.xml中註冊服務
  • 步驟3:在Activity中開啟Service服務

 

 

五、具體執行個體
  • 步驟1:定義IntentService的子類:傳入線程名稱、複寫onHandleIntent()方法
package com.example.carson_ho.demoforintentservice;import android.app.IntentService;import android.content.Intent;import android.util.Log;/** * Created by Carson_Ho on 16/9/28. */public class myIntentService extends IntentService {    /*建構函式*/    public myIntentService() {        //調用父類的建構函式        //建構函式參數=背景工作執行緒的名字        super("myIntentService");    }    /*複寫onHandleIntent()方法*/    //實現耗時任務的操作    @Override    protected void onHandleIntent(Intent intent) {        //根據Intent的不同進行不同的交易處理        String taskName = intent.getExtras().getString("taskName");        switch (taskName) {            case "task1":                Log.i("myIntentService", "do task1");                break;            case "task2":                Log.i("myIntentService", "do task2");                break;            default:                break;        }    }    @Override    public void onCreate() {        Log.i("myIntentService", "onCreate");        super.onCreate();    }    /*複寫onStartCommand()方法*/    //預設實現將請求的Intent添加到工作隊列裡    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.i("myIntentService", "onStartCommand");        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        Log.i("myIntentService", "onDestroy");        super.onDestroy();    }}
  • 步驟2:在Manifest.xml中註冊服務
<service android:name=".myIntentService">            <intent-filter >                <action android:name="cn.scu.finch"/>            </intent-filter>        </service>
  • 步驟3:在Activity中開啟Service服務
package com.example.carson_ho.demoforintentservice;import android.content.Intent;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);            //同一服務只會開啟一個背景工作執行緒            //在onHandleIntent函數裡依次處理intent請求。            Intent i = new Intent("cn.scu.finch");            Bundle bundle = new Bundle();            bundle.putString("taskName", "task1");            i.putExtras(bundle);            startService(i);            Intent i2 = new Intent("cn.scu.finch");            Bundle bundle2 = new Bundle();            bundle2.putString("taskName", "task2");            i2.putExtras(bundle2);            startService(i2);            startService(i);  //多次啟動        }    }
  • 結果

 

 

六、源碼分析

接下來,我們會通過源碼分析解決以下問題:

  • IntentService如何單獨開啟一個新的背景工作執行緒;
  • IntentService如何通過onStartCommand()傳遞給服務intent被依次插入到工作隊列中

問題1:IntentService如何單獨開啟一個新的背景工作執行緒

// IntentService源碼中的 onCreate() 方法@Overridepublic void onCreate() {    super.onCreate();    // HandlerThread繼承自Thread,內部封裝了 Looper    //通過執行個體化HandlerThread建立線程並啟動    //所以使用IntentService時不需要額外建立線程    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");    thread.start();    //獲得背景工作執行緒的 Looper,並維護自己的工作隊列    mServiceLooper = thread.getLooper();    //將上述獲得Looper與建立的mServiceHandler進行綁定    //建立的Handler是屬於背景工作執行緒的。    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 方法在背景工作執行緒中執行,執行完調用 stopSelf() 結束服務。        onHandleIntent((Intent)msg.obj);      //onHandleIntent 處理完成後 IntentService會調用 stopSelf() 自動停止。        stopSelf(msg.arg1);    }}////onHandleIntent()是一個抽象方法,使用時需要重寫的方法@WorkerThreadprotected abstract void onHandleIntent(Intent intent);

問題2:IntentService如何通過onStartCommand()傳遞給服務intent被依次插入到工作隊列中

public int onStartCommand(Intent intent, int flags, int startId) {    onStart(intent, startId);    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;}public void onStart(Intent intent, int startId) {    Message msg = mServiceHandler.obtainMessage();    msg.arg1 = startId;//把 intent 參數封裝到 message 的 obj 中,然後發送訊息,即添加到訊息佇列裡//這裡的Intent 就是啟動服務時startService(Intent) 裡的 Intent。    msg.obj = intent;    mServiceHandler.sendMessage(msg);}//清除訊息佇列中的訊息@Overridepublic void onDestroy() {    mServiceLooper.quit();}

  • 總結

    ?

    從上面源碼可以看出,IntentService本質是採用Handler & HandlerThread方式:

    1. 通過HandlerThread單獨開啟一個名為IntentService的線程
    2. 建立一個名叫ServiceHandler的內部Handler
    3. 把內部Handler與HandlerThread所對應的子線程進行綁定
    4. 通過onStartCommand()傳遞給服務intent,依次插入到工作隊列中,並逐個發送給onHandleIntent()
    5. 通過onHandleIntent()來依次處理所有Intent請求對象所對應的任務

因此我們通過複寫方法onHandleIntent(),再在裡面根據Intent的不同進行不同的線程操作就可以了

注意事項 工作任務隊列是順序執行的。

如果一個任務正在IntentService中執行,此時你再發送一個新的工作要求,這個新的任務會一直等待直到前面一個任務執行完畢才開始執行

原因:

  1. 由於onCreate() 方法只會調用一次,所以只會建立一個背景工作執行緒;
  2. 當多次調用 startService(Intent) 時(onStartCommand也會調用多次)其實並不會建立新的背景工作執行緒,只是把訊息加入訊息佇列中等待執行,所以,多次啟動 IntentService 會按順序執行事件
  3. 如果服務停止,會清除訊息佇列中的訊息,後續的事件得不到執行。

 

 

七、使用情境
  • 線程任務需要按順序、在後台執行的使用情境

    最常見的情境:離線下載

  • 由於所有的任務都在同一個Thread looper裡面來做,所以不符合多個資料同時請求的情境。

 

 

八、對比8.1 IntentService與Service的區別
  • 從屬性 & 作用上來說

   Service:依賴於應用程式的主線程(不是獨立的進程 or 線程)

不建議在Service中編寫耗時的邏輯和操作,否則會引起ANR;

  IntentService:建立一個背景工作執行緒來處理多線程任務   

  • Service需要主動調用stopSelft()來結束服務,而IntentService不需要(在所有intent被處理完後,系統會自動關閉服務)

8.2 IntentService與其他線程的區別
  • IntentService內部採用了HandlerThread實現,作用類似於後台線程;

  • 與後台線程相比,

    IntentService是一種後台服務

    ,優勢是:優先順序高(不容易被系統殺死),從而保證任務的執行

對於後台線程,若進程中沒有活動的四大組件,則該線程的優先順序非常低,容易被系統殺死,無法保證任務的執行

 

 

九、參考文章

  https://github.com/LRH1993/android_interview/blob/master/android/basis/IntentService.md

 

Android面試收集錄9 IntentService詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.