以下代碼是用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()開始的隊列裏面的任務是不能重複的。
如果小夥伴發現書寫中出現錯誤,或者有更好的封裝辦法,歡迎留言和私信。