(兩百六十五)學習使用 WorkManager 調度任務

學習https://developer.android.google.cn/topic/libraries/architecture/workmanager/basics

 

使用 WorkManager 調度任務

使用 WorkManager API 可以輕鬆地調度即使在應用退出或設備重啓時仍應運行的可延遲異步任務。

主要功能

  • 最高向後兼容到 API 14
    • 在運行 API 23 及以上級別的設備上使用 JobScheduler
    • 在運行 API 14-22 的設備上結合使用 BroadcastReceiver 和 AlarmManager
  • 添加網絡可用性或充電狀態等工作約束
  • 調度一次性或週期性異步任務
  • 監控和管理計劃任務
  • 將任務鏈接起來
  • 確保任務執行,即使應用或設備重啓也同樣執行任務
  • 遵循低電耗模式等省電功能

WorkManager 旨在用於可延遲運行(即不需要立即運行)並且在應用退出或設備重啓時必須能夠可靠運行的任務。例如:

  • 向後端服務發送日誌或分析數據
  • 定期將應用數據與服務器同步

WorkManager 不適用於應用進程結束時能夠安全終止的運行中後臺工作,也不適用於需要立即執行的任務。請查看後臺處理指南,瞭解哪種解決方案符合您的需求。

兼容API23之下的意義不是很大了,現在都到Android R了,API 22還是L,5年前的機型了,可以認爲現在主流機型的內部實現應該是用的JobScheduler。亮點暫時看到的是可重啓、加約束和低功耗

 

WorkManager 入門指南

通過 WorkManager,您可以輕鬆設置任務並提交給系統,以在您指定的條件下運行。如需進一步瞭解 WorkManager 是不是適合您任務的解決方案,請參閱後臺處理指南

在本指南中,您將瞭解到如何執行以下操作:

  • 將 WorkManager 添加到您的 Android 項目中
  • 創建後臺任務
  • 配置運行任務的方式和時間
  • 將任務提交給系統

要了解 WorkManager 功能(例如處理週期性工作、創建工作鏈以及取消工作),請參閱方法指南

 

將 WorkManager 添加到您的 Android 項目中

按照 WorkManager 版本說明中的說明,使用 Java 或 Kotlin 語言將 WorkManager 依賴項添加到您的 Android 項目中。

https://developer.android.google.cn/jetpack/androidx/releases/work#declaring_dependencies

聲明依賴項

如需添加 WorkManager 的依賴項,您必須將 Google Maven 代碼庫添加到項目中:

在應用或模塊的 build.gradle 文件中添加所需工件的依賴項:

    dependencies {
      def work_version = "2.3.4"

        // (Java only)
        implementation "androidx.work:work-runtime:$work_version"

        // Kotlin + coroutines
        implementation "androidx.work:work-runtime-ktx:$work_version"

        // optional - RxJava2 support
        implementation "androidx.work:work-rxjava2:$work_version"

        // optional - GCMNetworkManager support
        implementation "androidx.work:work-gcm:$work_version"

        // optional - Test helpers
        androidTestImplementation "androidx.work:work-testing:$work_version"
      }
    

 

創建後臺任務

任務是使用 Worker 類定義的。doWork() 方法在 WorkManager 提供的後臺線程上同步運行。

要創建後臺任務,請擴展 Worker 類並替換 doWork() 方法。例如,要創建上傳圖像的 Worker,您可以執行以下操作:

    public class UploadWorker extends Worker {

        public UploadWorker(
            @NonNull Context context,
            @NonNull WorkerParameters params) {
            super(context, params);
        }

        @Override
        public Result doWork() {
          // Do the work here--in this case, upload the images.

          uploadImages()

          // Indicate whether the task finished successfully with the Result
          return Result.success()
        }
    }
    

doWork() 返回的 Result 會通知 WorkManager 任務是否:

  • 已成功完成:Result.success()
  • 已失敗:Result.failure()
  • 需要稍後重試:Result.retry()

注意Worker 是運行工作的最簡單方式。要了解 Worker 的更多高級選項,請參閱 WorkManager 線程指南

 

配置運行任務的方式和時間

Worker 定義工作單元,WorkRequest 則定義工作的運行方式和時間。任務可以是一次性的,也可以是週期性的。對於一次性 WorkRequest,請使用 OneTimeWorkRequest,對於週期性工作,請使用 PeriodicWorkRequest。要詳細瞭解如何調度週期性工作,請參閱週期性工作文檔

在本例中,爲 UploadWorker 構建 WorkRequest 最簡單的示例爲:

    OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class)
            .build()
    

WorkRequest 中還可以包含其他信息,例如任務在運行時應遵循的約束、工作輸入、延遲,以及重試工作的退避時間政策。關於這些選項,在定義工作指南中有更詳細的說明。

 

將您的任務提交給系統

定義 WorkRequest 之後,您現在可以通過 WorkManager 使用 enqueue() 方法來調度它。

    WorkManager.getInstance(myContext).enqueue(uploadWorkRequest);
    

執行 Worker 的確切時間取決於 WorkRequest 中使用的約束以及系統優化。WorkManager 的設計目的就是要在這些限制下提供儘可能好的表現。

 

定義工作請求

入門指南介紹瞭如何創建簡單的 WorkRequest 並將其加入隊列。

在本指南中,您將瞭解如何自定義工作請求來處理常見用例:

  • 處理網絡可用性等任務約束
  • 確保任務延遲一定時間再執行
  • 處理任務重試和退避
  • 處理任務輸入和輸出
  • 使用標記對任務進行分組

工作約束

您可以向工作添加 Constraints,以指明工作何時可以運行。

例如,您可以指定工作應僅在設備空閒且接通電源時運行。

下面的代碼展示瞭如何將這些約束添加到 OneTimeWorkRequest。有關所支持約束的完整列表,請參閱 Constraints.Builder 參考文檔

KotlinJava

    // Create a Constraints object that defines when the task should run
    Constraints constraints = new Constraints.Builder()
        .setRequiresDeviceIdle(true)
        .setRequiresCharging(true)
         .build();

    // ...then create a OneTimeWorkRequest that uses those constraints
    OneTimeWorkRequest compressionWork =
                    new OneTimeWorkRequest.Builder(CompressWorker.class)
         .setConstraints(constraints)
         .build();
    

如果指定了多個約束,您的任務將僅在滿足所有約束時纔會運行。

如果在任務運行期間某個約束不再得到滿足,則 WorkManager 將停止工作器。當約束繼續得到滿足時,系統將重新嘗試執行該任務。

這個挺有用的,不需要寫一堆狀態監聽加判斷了

https://developer.android.google.cn/reference/androidx/work/Constraints.Builder#setRequiredNetworkType(androidx.work.NetworkType)

看約束支持

  • setRequiredNetworkType
  • setRequiresBatteryNotLow
  • setRequiresCharging
  • setRequiresDeviceIdle
  • setRequiresStorageNotLow
  • setTriggerContentMaxDelay
  • setTriggerContentUpdateDelay

 

初始延遲

如果您的工作沒有約束,或者工作加入隊列時所有約束均已得到滿足,則系統可能會選擇立即運行任務。如果您不希望任務立即運行,則可以將工作指定爲在經過一段最短初始延遲時間後再啓動。

下面的示例展示瞭如何將任務設置爲在加入隊列後至少經過 10 分鐘再運行。

KotlinJava

    OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class)
            .setInitialDelay(10, TimeUnit.MINUTES)
            .build();

    

注意:執行工作器的確切時間還取決於 WorkRequest 中使用的約束和系統優化方式。WorkManager 經過設計,能夠在滿足這些約束的情況下提供可能的最佳行爲。

 

重試和退避政策

如果您需要讓 WorkManager 重新嘗試執行您的任務,可以從工作器返回 Result.retry()

然後,系統會根據默認的退避延遲時間和政策重新調度您的工作。退避延遲時間指定了重試工作前的最短等待時間。退避政策定義了在後續重試過程中,退避延遲時間隨時間以怎樣的方式增長;默認情況下按 EXPONENTIAL 延長。

以下是自定義退避延遲時間和政策的示例。

KotlinJava

    OneTimeWorkRequest uploadWorkRequest =
        new OneTimeWorkRequest.Builder(UploadWorker.class)
            .setBackoffCriteria(
                    BackoffPolicy.LINEAR,
                    OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                    TimeUnit.MILLISECONDS)
            .build();
    

 

定義任務的輸入/輸出

您的任務可能需要數據以輸入參數的形式傳入,或者將數據返回爲結果。例如,某個任務負責處理圖像上傳,它要求以要上傳的圖像的 URI 爲輸入,並且可能要求用已上傳圖像的網址作爲輸出。

輸入和輸出值以鍵值對的形式存儲在 Data 對象中。下面的代碼展示瞭如何在 WorkRequest 中設置輸入數據。

KotlinJava

    Data imageData = new Data.Builder()
                    .putString(Constants.KEY_IMAGE_URI, imageUriString)
                    .build();

    OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class)
            .setInputData(imageData)
            .build();
    

Worker 類可通過調用 Worker.getInputData() 訪問輸入參數。

類似地,Data 類可用於輸出返回值。如需返回 Data 對象,請將它添加到 Result.success()Result.failure() 時的 Result 中,如下所示。

KotlinJava

    public class UploadWorker extends Worker {

        public UploadWorker(
            @NonNull Context context,
            @NonNull WorkerParameters params) {
            super(context, params);
        }

        @Override
        public Result doWork() {

            // Get the input
            String imageUriInput =
                    getInputData().getString(Constants.KEY_IMAGE_URI);
            // TODO: validate inputs.
            // Do the work
            Response response = uploadFile(imageUriInput);

            // Create the output of the work
            Data outputData = new Data.Builder
                    .putString(Constants.KEY_IMAGE_URL, response.imageUrl)
                    .build();

            // Return the output
            return Result.success(outputData);
        }
    }
    

注意:按照設計,Data 對象應該很小,值可以是字符串、基元類型或數組變體。如果需要將更多數據傳入和傳出工作器,應該將數據放在其他位置,例如 Room 數據庫。Data 對象的大小上限爲 10KB。

 

標記工作

您可以通過爲任意 WorkRequest 對象分配標記字符串,按邏輯對任務進行分組。這樣您就可以對使用特定標記的所有任務執行操作。

例如,WorkManager.cancelAllWorkByTag(String) 會取消使用特定標記的所有任務,而 WorkManager.getWorkInfosByTagLiveData(String) 會返回 LiveData 和具有該標記的所有任務的狀態列表。

以下代碼展示瞭如何使用 WorkRequest.Builder.addTag(String) 向任務添加“cleanup”標記:

KotlinJava

    OneTimeWorkRequest cacheCleanupTask =
            new OneTimeWorkRequest.Builder(CacheCleanupWorker.class)
        .setConstraints(constraints)
        .addTag("cleanup")
        .build();

 

總結

WorkManager主要用於不是即時的對穩定性和執行條件有要求的異步任務中,在系統和應用重啓後也可得到執行。

使用方法主要是定義任務,添加約束和進行任務隊列添加。
   

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章