WorkManager使用記錄

以下代碼是用Java語言編寫的,也並沒有兼容AndroidX,如果項目兼容AndroidX的話,WorkManager實例的獲取是有點區別的,Kotlin就可以去官網了,大概原理差不多,以下資料來源於官網文檔,正好先用到一點,當做筆記記錄一下。


內容一覽:

  • 用途、優點、添加依賴、用法思路

  • 創建後臺任務類、配置WorkManager請求參數以及執行

  • 定義任務約束、任務延遲執行

  • 定義任務的輸入和輸出、爲任務添加標籤、取消任務

  •  後臺任務狀態的監聽

  •  設定一次只能激活一個特定名稱的後臺任務


用途

屬於JetPack結構組件,用於進行後臺任務



優點

操作簡單,穩定性強,對於異步任務,即使APP退出運行或者設備重啓,都能很好的保證任務的順利執行


添加依賴

implementation  "android.arch.work:work-runtime:1.0.1"   (Java)

 



用法思路:

新建一個類繼承Woker,並實現其方法,在其doWork()方法中進行後臺任務,然後再根據返回的狀態對任務結果進行相應的處理
    



創建後臺任務類:


    

Class DemoWorker extends Worker {
        public DemoWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
            super(context, workerParams);
        }
    }
    
    @NonNull
    @Override
    public Result doWork() {
        //在這裏進行後臺任務
        
        return Result.success(); //此處返回值下面講述
    }


    doWork()方法的返回值
    Result.success():已成功完成
    Result.failure() : 已失敗文
    Result.retry():稍後重試
    



配置WorkManager請求參數以及執行
    

構建一次性任務(只執行一次,執行完就自動結束)


    /**
     * OneTimeWorkRequest : 專門用於構建一次性任務
     * DemoWorker: 指的是當前創建的後臺任務類名稱 
     */
    OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(DemoWorker.class).build();


 構建週期性任務(只隔一個週期執行一次,執行完就自動結束,週期間隔至少爲15分鐘)

   /**
     * PeriodicWorkRequest : 專門用於構建週期性任務
     * 15 :計數單位
     * TimeUnit.MINUTES : 以分鐘爲計時單位
     * DemoWorker: 指的是當前創建的後臺任務類名稱 
     */
     PeriodicWorkRequest request = new PeriodicWorkRequest.Builder(DeviceSyncWorker.class, 15, TimeUnit.MINUTES)
                .build();


 執行任務:(通過enqueue方法執行任務)

  WorkManager.getInstance().enqueue(request);

 

定義任務約束:


 添加約束:網絡連接

Constraints constraints = new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build();


然後將constraints加入任務構建中,例如:

 OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(DemoWorker.class)
        .setConstraints(constraints)
        .build();
    


    約束的種類:
        addContentUriTrigger:
        setRequiredNetworkType:網絡連接狀態約束(需要網絡,不需要網絡,不限時的網絡,非漫遊網絡,計量網絡連接)
        setRequiresBatteryNotLow:設備電池電量處於可接受的水平纔可以執行任務
        setRequiresCharging:設備充電時纔可以執行任務
        setRequiresDeviceIdle:設備空閒狀態時纔可以執行任務
        setRequiresStorageNotLow:設備存儲處於可接受的範圍纔可以執行任務
        setTriggerContentMaxDelay:設置從第一次檢測到內容更改到計劃的時間所允許的最大延遲
        setTriggerContentUpdateDelay:設置從第一次檢測到內容更改到計劃的時間所允許的延遲
  


     
任務初始延遲:


 如果不希望任務立即執行,則可以將任務指定爲在經過最短的初始延遲後啓動,例如:

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

 

定義任務的輸入和輸出


    使用場景:任務需要數據以傳入參數的形式傳入,或者將數據返回爲結果(
    注意:Data 對象應該很小,值可以是字符串、基元類型或數組變體。
         如果需要將更多數據傳入和傳出工作器,應該將數據放在其他位置,例如 Room 數據庫。Data 對象的大小上限爲 10KB。
    例如:(此處是官方的例子)
    場景是:後臺任務是處理圖像上傳,要求以要上傳圖片的URL爲輸入,並且要求用已上傳圖像的網址作爲輸出
    代碼如下:
    
  

 /**
     * Constants.KEY_IMAGE_URI :自定義的字符串常量
     * imageUriString:要上傳的圖片URL
     * UploadWorker:後臺任務類的名稱
     */
    Data imageData = new Data.Builder
                    .putString(Constants.KEY_IMAGE_URI, imageUriString)
                    .build();

    OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class)
            .setInputData(imageData)
            .build()
    
    
    輸入的Data數據可在doWork()方法中進行獲取,例如:
    @NonNull
    @Override
    public Result doWork() {
        
        String dataInput = getInputData().getString(Constants.KEY_IMAGE_URI);
        
        //後臺任務返回數據  uploadFile(dataInput)====>>> 後臺任務
        舉例: Response response = uploadFile(dataInput)
        
        //將後臺任務返回的數據中取出要返回的數據,放入Data中
        Data outputData = new Data.Builder
                    .putString(Constants.KEY_IMAGE_URI, response.imageUrl)
                    .build();
        
        return Result.success(outputData); 
    }

 

爲任務添加標籤


    添加標籤的好處:通過標籤來取消後臺任務請求(可以將同一標籤下所有的後臺任務請求全部取消)
    例如:

添加標籤:
    OneTimeWorkRequest cacheCleanupTask = new OneTimeWorkRequest.Builder(DemoWorker.class)
        .setConstraints(constraints)
        .addTag("cleanup")
        .build();
通過標籤取消任務:
    WorkManager.getInstance().cancelAllWorkByTag("cleanup");


取消任務:

通過ID取消指定單個任務:
        WorkManager.getInstance().cancelWorkById(request.id);
通過標籤取消標籤名下的所有任務:
        WorkManager.getInstance().cancelAllWorkByTag("cleanup");
一次性取消全部任務:
        WorkManager.getInstance().cancelAllWork();

 

後臺任務狀態的監聽:


    通過id監聽單個後臺任務請求的運行結果:

WorkManager.getInstance(myContext).getWorkInfoByIdLiveData(uploadWorkRequest.getId())
            .observe(lifecycleOwner, new Observer<WorkInfo>() {
                @Override
                public void onChanged(@Nullable WorkInfo workInfo) {
                  if (workInfo != null && workInfo.state == WorkInfo.State.SUCCEEDED) {
                      Log.e(TAG,"Success");
                  }
                }
            });


    
    通過Tag標籤監聽同一標籤下所有後臺任務請求的運行結果:

 WorkManager.getInstance().getWorkInfosByTagLiveData("tag").observe(this, new android.arch.lifecycle.Observer<List<WorkInfo>>() {
            @Override
            public void onChanged(@Nullable List<WorkInfo> workInfos) {
                for (WorkInfo workInfo : workInfos) {
                    if (workInfo != null && workInfo.getState() == WorkInfo.State.SUCCEEDED) {
                        Log.e(TAG,"Success");
                    }
                }
            }
        });


    如果後臺任務執行是通過enqueueUniqueWork(“workName")執行的,可以通過getWorkInfosForUniqueWorkLiveData監聽後臺任務運行結果:

WorkManager.getInstance().getWorkInfosForUniqueWorkLiveData("workName").observe(this, new android.arch.lifecycle.Observer<List<WorkInfo>>() {
            @Override
            public void onChanged(@Nullable List<WorkInfo> workInfos) {
                if (workInfos == null) {
                    Log.e(TAG,"Success");
                    return;
                }
                for (WorkInfo workInfo : workInfos) {
                    if (workInfo != null && workInfo.getState() == WorkInfo.State.SUCCEEDED) {
                        Log.e(TAG,"Success");
                    }
                }
            }
        });    

設定一次只能激活一個特定名稱的後臺任務

  /**
     * enqueueUniqueWork:通過此方法設定一次只能激活一個特定名稱的後臺任務
     * singleWork:進行此操作的唯一名稱,之後狀態監聽要獲取此名稱
     * ExistingWorkPolicy:工作策略(REPLACE:取消現有的序列並用新序列替換   KEEP:保持現有順序並忽略新的請求  
                             APPEND:將新序列附加到現有學列,在現有序列的最後一個任務完成後運行新序列的第一個任務)
     * request:自行構建的一次性任務或者週期性任務
     * 如何監聽此任務狀態,上述有代碼
     */
    WorkManager.getInstance().enqueueUniqueWork("singleWork", ExistingWorkPolicy.KEEP, request);

 


開啓鏈式任務


注意:WorkerManager要求必須在前一個後臺任務運行成功後,下一個後臺任務纔會運行,也就是說,如果某個後臺任務運行失敗,或者被取消了,那麼接下來的後臺任務就都得不到運行了。


比如我們有A,B,C三個任務,我們需要順序執行。那我們就可以

使用beginWith()方法用於開啓一個鏈式任務(任務允許重複),後面接上後臺任務,可使用then()方法鏈接即可;

WorkManager.getInstance().beginWith(A).then(B).then(C).enqueue();


使用beginUniqueWork()方法用於開啓一個鏈式任務(任務不允許重複)

WorkManager.getInstance().beginUniqueWork("unique", ExistingWorkPolicy.KEEP, requestA)
                   .then(requestB)
                   .then(requestC)
                   .enqueue();


beginWith(),beginUniqueWork()兩個函數開啓的隊列的唯一區別在於,隊列裏面的任務能不能重複。
beginWith()開始的隊列裏面的任務是可以重複的,beginUniqueWork()開始的隊列裏面的任務是不能重複的。

 


 

如果小夥伴發現書寫中出現錯誤,或者有更好的封裝辦法,歡迎留言和私信。

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