首頁 > 軟體

Android開發Jetpack元件WorkManager用例詳解

2022-02-09 13:00:18

一、簡介

WorkManager 用於處理 Android 後臺任務。我們只需要設定好任務內容、何時執行,剩下的工作就可以完全交給系統處理。它會自動向下相容,在不同的 Android 版本上採用不同的實現方案。

由於是交給系統排程的,它可以保證應用退出甚至手機重啟後,任務依然能夠得到執行。WorkManager 很適合執行一些定期和伺服器互動的任務,比如週期性的同步資料等等。並且,WorkManager 還支援週期性任務、鏈式任務。

需要注意的是,WorkManager 不能保證任務一定能夠準時執行,這是因為系統為了減少電量消耗,會將觸發事件臨近的幾個任務放在一起執行,以減少 CPU 被喚醒的次數,延長電池使用時間。

另外,在國產手機上 WorkManager 可能無法正常執行,這是因為絕大多數手機廠商客製化 Android 系統時,會新增一個“一鍵關閉”的功能,這樣被殺死後的應用程式,既無法接收廣播,也不能執行 WorkManager 的後臺任務。國產手機增加此功能也是迫於無奈,主要是因為市面上有太多的惡意應用想要霸佔後臺。所以,我們在國產手機上不要使用 WorkManager 去實現核心功能。

二、匯入

在 app/build.gradle 中新增依賴:

implementation 'androidx.work:work-runtime:2.3.2'

三、基本使用

WorkManager 的用法分為三步:

  • 定義一個後臺任務
  • 設定任務執行條件
  • 將任務傳給 WorkManager

3.1 定義後臺任務

建立一個 SimpleWorker 類,繼承自 Worker:

class SimpleWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        Log.d("~~~", "do something")
        return Result.success()
    }
}

Result.success()表示任務執行成功

Result.failure() 表示任務執行失敗

Result.retry() 表示任務需要重試。這個方法需要配合任務重試設定一起使用

3.2 設定任務執行條件

3.2.1 只需執行一次的任務

使用 OneTimeWorkRequest 構建只需執行一次的任務

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java).build()

3.2.2 週期性執行的任務

使用 PeriodicWorkRequest 構建週期性執行的任務

val request = PeriodicWorkRequest.Builder(SimpleWorker::class.java, 15, TimeUnit.MINUTES).build()

為了減少耗電量,PeriodicWorkRequest 要求任務執行週期不得短於十五分鐘,檢視原始碼可以發現,如果傳入的值短於十五分鐘,系統會列印一條警告,然後自動將週期設定成十五分鐘:

public static final long MIN_PERIODIC_INTERVAL_MILLIS = 15 * 60 * 1000L; // 15 minutes.
/**
 * Sets the periodic interval for this unit of work.
 *
 * @param intervalDuration The interval in milliseconds
 */
public void setPeriodic(long intervalDuration) {
    if (intervalDuration < MIN_PERIODIC_INTERVAL_MILLIS) {
        Logger.get().warning(TAG, String.format(
                "Interval duration lesser than minimum allowed value; Changed to %s",
                MIN_PERIODIC_INTERVAL_MILLIS));
        intervalDuration = MIN_PERIODIC_INTERVAL_MILLIS;
    }
    setPeriodic(intervalDuration, intervalDuration);
}

3.3 將任務傳給 WorkManager

WorkManager.getInstance(this).enqueue(request)

這就是 WorkManager 的基本使用。

四、高階設定

4.1 設定任務延遲執行

通過 setInitialDelay 方法設定延遲時間

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
   .setInitialDelay(5, TimeUnit.MINUTES)
   .build()

4.2 給任務新增標籤

通過 addTag 方法新增標籤:

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .addTag("simple")
    .build()

新增標籤的作用是,方便我們根據標籤取消任務。

4.3 取消任務

4.3.1 根據標籤取消任務

WorkManager.getInstance(this).cancelAllWorkByTag("simple")

4.3.2 根據 request 的 id 取消任務

WorkManager.getInstance(this).cancelWorkById(request.id)

4.3.3 取消所有任務

WorkManager.getInstance(this).cancelAllWork()

4.4 任務重試

通過 setBackoffCriteria 設定任務重試:

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .setBackoffCriteria(BackoffPolicy.LINEAR, 10, TimeUnit.SECONDS)
    .build()

前文說到,Result.retry() 表示任務需要重試,這個方法需要配合任務重試設定一起使用。任務重試設定就是指這個 setBackoffCriteria 方法,它傳入了三個值,第二個值和第三個值表示重試時間設定。第一個值表示重試延遲的形式,有兩個值可供選擇:

  • BackoffPolicy.LINEAR 重試時間每次呈線性增長,按照此例中的設定,每次重試時間就是 10s,20s,30s,40s…
  • BackoffPolicy.EXPONENTIAL 重試時間每次呈指數級增長,按照此例中的設定,每次重試時間就是 10s,20s,40s,80s…

4.5 監聽任務結果

WorkManager.getInstance(this).getWorkInfoByIdLiveData(request.id).observe(this) {
    Log.d("~~~", "state = ${it.state}, tags = ${it.tags.toList()}")
    when (it.state) {
        WorkInfo.State.SUCCEEDED -> Log.d("~~~", "success")
        WorkInfo.State.FAILED -> Log.d("~~~", "fail")
        WorkInfo.State.RUNNING -> Log.d("~~~", "running")
        WorkInfo.State.ENQUEUED -> Log.d("~~~", "enqueued")
        WorkInfo.State.CANCELLED -> Log.d("~~~", "cancelled")
        WorkInfo.State.BLOCKED -> Log.d("~~~", "blocked")
    }
}

首先通過 getWorkInfoByIdLiveData 獲得任務資訊的 LiveData<WorkInfo> 資料,然後觀察此資料即可。也可以通過 getWorkInfosByTagLiveData 獲得相同 Tag 的 LiveData<List<WorkInfo>>,觀察這個任務資訊列表。通過 WorkInfo 的 getState 方法獲取任務狀態,主要用到的狀態有 WorkInfo.State.SUCCEEDED 和 WorkInfo.State.FAILED,標誌著任務的成功和失敗。

4.6 傳遞資料

val request = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .setInputData(Data.Builder().apply {
        putString("key", "value")
    }.build())
    .build()

SimpleWorker 類中讀取此資料:

inputData.getString("key")

4.7 鏈式任務

val first = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .build()
val second = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .build()
val third = OneTimeWorkRequest.Builder(SimpleWorker::class.java)
    .build()
WorkManager.getInstance(this)
    .beginWith(first)
    .then(second)
    .then(third)
    .enqueue()

通過 beginWith 發起鏈式任務,然後字尾 then 即可,任務會按照連線順序依次執行。WorkManager 要求必須在上一個任務執行成功後,才會執行下一個任務。也就是說任何一個任務的失敗都會導致鏈式任務的中斷。

以上就是Android開發Jetpack元件WorkManager用例詳解的詳細內容,更多關於Android Jetpack元件WorkManager的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com