天天看點

Android多線程:IntentService用法&源碼分析前言目錄1. 定義2. 作用3. 使用場景4. 使用步驟5. 執行個體應用6. 源碼分析7. 注意事項8. 對比9. 總結請幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!

前言

  • 多線程的應用在Android開發中是非常常見的,常用方法主要有:
    1. 繼承Thread類
    2. 實作Runnable接口
    3. AsyncTask
    4. Handler
    5. HandlerThread
    6. IntentService
  • 今天,我将全面解析多線程其中一種常見用法:

    IntentService

目錄

Android多線程:IntentService用法&源碼分析前言目錄1. 定義2. 作用3. 使用場景4. 使用步驟5. 執行個體應用6. 源碼分析7. 注意事項8. 對比9. 總結請幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!

1. 定義

Android

裡的一個封裝類,繼承四大元件之一的

Service

2. 作用

處理異步請求 & 實作多線程

3. 使用場景

線程任務 需 按順序、在背景執行

  1. 最常見的場景:離線下載下傳
  2. 不符合多個資料同時請求的場景:所有的任務都在同一個

    Thread looper

    裡執行

4. 使用步驟

步驟1:定義

IntentService

的子類

需 傳入線程名稱、複寫

onHandleIntent()

方法

步驟2:在

Manifest.xml

中注冊服務

步驟3:在

Activity

中開啟

Service

服務

5. 執行個體應用

步驟1:定義

IntentService

的子類

傳入線程名稱、複寫

onHandleIntent()

方法
public class myIntentService extends IntentService {

  /** 
    * 在構造函數中傳入線程名字
    **/  
    public myIntentService() {
        // 調用父類的構造函數
        // 參數 = 工作線程的名字
        super("myIntentService");
    }

   /** 
     * 複寫onHandleIntent()方法
     * 根據 Intent實作 耗時任務 操作
     **/  
    @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服務

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

            // 同一服務隻會開啟1個工作線程
            // 在onHandleIntent()函數裡,依次處理傳入的Intent請求
            // 将請求通過Bundle對象傳入到Intent,再傳入到服務裡

            // 請求1
            Intent i = new Intent("cn.scu.finch");
            Bundle bundle = new Bundle();
            bundle.putString("taskName", "task1");
            i.putExtras(bundle);
            startService(i);

            // 請求2
            Intent i2 = new Intent("cn.scu.finch");
            Bundle bundle2 = new Bundle();
            bundle2.putString("taskName", "task2");
            i2.putExtras(bundle2);
            startService(i2);

            startService(i);  //多次啟動
        }
    }
           

測試結果

Android多線程:IntentService用法&amp;源碼分析前言目錄1. 定義2. 作用3. 使用場景4. 使用步驟5. 執行個體應用6. 源碼分析7. 注意事項8. 對比9. 總結請幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!

6. 源碼分析

  • IntentService

    的源碼工作流程如下:
Android多線程:IntentService用法&amp;源碼分析前言目錄1. 定義2. 作用3. 使用場景4. 使用步驟5. 執行個體應用6. 源碼分析7. 注意事項8. 對比9. 總結請幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!

特别注意:若啟動

IntentService

多次,那麼 每個耗時操作 則 以隊列的方式 在

IntentService

onHandleIntent

回調方法中依次執行,執行完自動結束

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

  • IntentService

    如何單獨開啟1個新的工作線程
  • IntentService

    如何通過

    onStartCommand()

    将Intent 傳遞給服務 & 依次插入到工作隊列中

問題1:IntentService如何單獨開啟1個新的工作線程

主要分析内容 =

IntentService

源碼中的

onCreate()

方法

@Override
public void onCreate() {
    super.onCreate();
    
    // 1. 通過執行個體化andlerThread建立線程 & 啟動;故 使用IntentService時,不需額外建立線程
    // HandlerThread繼承自Thread,内部封裝了 Looper
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();
  
    // 2. 獲得工作線程的 Looper & 維護自己的工作隊列
    mServiceLooper = thread.getLooper();

    // 3. 建立mServiceHandler & 綁定上述獲得Looper
    // 建立的Handler 屬于工作線程 ->>分析1
    mServiceHandler = new ServiceHandler(mServiceLooper); 
}


   /** 
     * 分析1:ServiceHandler源碼分析
     **/ 
     private final class ServiceHandler extends Handler {

         // 構造函數
         public ServiceHandler(Looper looper) {
         super(looper);
       }

        // IntentService的handleMessage()把接收的消息交給onHandleIntent()處理
        @Override
         public void handleMessage(Message msg) {
  
          // onHandleIntent 方法在工作線程中執行
          // onHandleIntent() = 抽象方法,使用時需重寫 ->>分析2
          onHandleIntent((Intent)msg.obj);
          // 執行完調用 stopSelf() 結束服務
          stopSelf(msg.arg1);

    }
}

   /** 
     * 分析2: onHandleIntent()源碼分析
     * onHandleIntent() = 抽象方法,使用時需重寫
     **/ 
      @WorkerThread
      protected abstract void onHandleIntent(Intent intent);
           

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

/** 
  * onStartCommand()源碼分析
  * onHandleIntent() = 抽象方法,使用時需重寫
  **/ 
  public int onStartCommand(Intent intent, int flags, int startId) {

    // 調用onStart()->>分析1
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

/** 
  * 分析1:onStart(intent, startId)
  **/ 
  public void onStart(Intent intent, int startId) {

  	// 1. 獲得ServiceHandler消息的引用
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;

    // 2. 把 Intent參數 包裝到 message 的 obj 發送消息中,
    //這裡的Intent  = 啟動服務時startService(Intent) 裡傳入的 Intent
    msg.obj = intent;

    // 3. 發送消息,即 添加到消息隊列裡
    mServiceHandler.sendMessage(msg);
}

           

總結

從上面源碼可看出:

IntentService

本質 =

Handler

+

HandlerThread

  1. 通過

    HandlerThread

    單獨開啟1個工作線程:

    IntentService

  2. 建立1個内部

    Handler

    ServiceHandler

  3. 綁定

    ServiceHandler

    IntentService

  4. 通過

    onStartCommand()

    傳遞服務

    intent

    ServiceHandler

    、依次插入

    Intent

    到工作隊列中 & 逐個發送給

    onHandleIntent()

  5. 通過

    onHandleIntent()

    依次處理所有

    Intent

    對象所對應的任務
是以我們通過複寫

onHandleIntent()

& 在裡面 根據

Intent

的不同進行不同線程操作 即可

7. 注意事項

注意事項1. 工作任務隊列 = 順序執行

即 若一個任務正在

IntentService

中執行,此時你再發送1個新的任務請求,這個新的任務會一直等待直到前面一個任務執行完畢後才開始執行
  • 原因:
  1. 由于

    onCreate()

    隻會調用一次 = 隻會建立1個工作線程;
  2. 當多次調用

    startService(Intent)

    時(即

    onStartCommand()

    也會調用多次),其實不會建立新的工作線程,隻是把消息加入消息隊列中 & 等待執行。

    3, 是以,多次啟動 IntentService 會按順序執行事件

若服務停止,則會清除消息隊列中的消息,後續的事件不執行

注意事項2:不建議通過 bindService() 啟動 IntentService

原因:

// 在IntentService中,onBind()`預設傳回null
@Override
public IBinder onBind(Intent intent) {
    return null;
}
           
  • 采用

    bindService()

    啟動

    IntentService

    的生命周期如下:
onCreate() ->> onBind() ->> onunbind()->> onDestory()
  • 即,并不會調用

    onStart()

    onStartcommand()

    ,故不會将消息發送到消息隊列,那麼onHandleIntent()将不會回調,即無法實作多線程的操作
此時,你應該使用

Service

,而不是

IntentService

8. 對比

8.1 IntentService與Service的差別

Android多線程:IntentService用法&amp;源碼分析前言目錄1. 定義2. 作用3. 使用場景4. 使用步驟5. 執行個體應用6. 源碼分析7. 注意事項8. 對比9. 總結請幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!

8.2 IntentService與其他線程的差別

Android多線程:IntentService用法&amp;源碼分析前言目錄1. 定義2. 作用3. 使用場景4. 使用步驟5. 執行個體應用6. 源碼分析7. 注意事項8. 對比9. 總結請幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!

9. 總結

  • 本文主要 全面介紹了 多線程

    IntentService

    用法 & 源碼
  • 接下來,我會繼續講解

    Android

    開發中關于多線程的知識,包括繼承

    Thread

    類、實作

    Runnable

    接口、

    Handler

    等等,感興趣的同學可以繼續關注carson_ho的微信公衆号
    Android多線程:IntentService用法&amp;源碼分析前言目錄1. 定義2. 作用3. 使用場景4. 使用步驟5. 執行個體應用6. 源碼分析7. 注意事項8. 對比9. 總結請幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!
    Android多線程:IntentService用法&amp;源碼分析前言目錄1. 定義2. 作用3. 使用場景4. 使用步驟5. 執行個體應用6. 源碼分析7. 注意事項8. 對比9. 總結請幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!

請幫頂 / 評論點贊!因為你的鼓勵是我寫作的最大動力!