日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Jetpack WorkManager的使用-完全解析

發布時間:2024/4/15 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Jetpack WorkManager的使用-完全解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

谷歌官方API介紹

兼容范圍廣

Pangu-Immortal (Pangu-Immortal) · GitHub

WorkManager最低能兼容API Level 14,并且不需要你的設備安裝有Google Play Services。因此,你不用過于擔心兼容性問題,因為API Level 14已經能夠兼容幾乎100%的設備了。

WorkManager依據設備情況選擇方案

WorkManager能依據設備的情況,選擇不同的執行方案。在API Level 23+,通過JobScheduler來完成任務,而在API Level 23以下的設備中,通過AlarmManagerBroadcast Receivers組合完成任務。但無論采用哪種方案,任務最終都是交由Executor來完成。

源代碼:https://github.com/yugu88/Jetpack-demos

WorkManager的兩個重要特點

1.針對不需要及時完成的任務

比如,發送應用程序日志,同步應用程序數據,備份用戶數據等。站在業務的角度,這些任務都不需要立即完成,如果我們自己來管理這些任務,邏輯可能會非常復雜,若API使用不恰當,可能會消耗大量電量。

2.保證任務一定會被執行

WorkManager能保證任務一定會被執行,即使你的應用程序當前不在運行中,哪怕你的設備重啟,任務仍然會在適當的時候被執行。這是因為WorkManager有自己的數據庫,關于任務的所有信息和數據都保存在這個數據庫中,因此,只要你的任務交給了WorkManager,哪怕你的應用程序徹底退出,或者設備重新啟動,WorkManager依然能夠保證完成你交給的任務

注意:WorkManager不是一種新的工作線程,它的出現不是為了替代其它類型的工作線程。工作線程通常立即運行,并在執行完成后給到用戶反饋。而WorkManager不是即時的,它不能保證任務能立即得到執行。

在項目中使用WorkManager

1.在app的build.gradle中添加依賴。

dependencies {def versions = "2.2.0"implementation "androidx.work:work-runtime:$versions" }

2.使用Worker定義任務 。

繼承Worker類,覆蓋doWork()方法,所有需要在任務中執行的代碼都在該方法中編寫。

public class UploadLogWorker extends Worker {public UploadLogWorker(@NonNull Context context, @NonNull WorkerParameters workerParams){super(context, workerParams);}/*** 耗時的任務,在doWork()方法中執行* */@NonNull@Overridepublic Result doWork(){Log.e("UploadLogWorker", "doWork()");return Result.success();} }

doWork()方法有三種類型的返回值:

  • 執行成功返回Result.success()
  • 執行失敗返回Result.failure()
  • 需要重新執行返回Result.retry()

3.使用WorkRequest配置任務。通過WorkRequest配置我們的任務何時運行以及如何運行

  • 設置任務觸發條件。例如,我們可以設置在設備處于充電,網絡已連接,且電池電量充足的狀態下,才出發我們設置的任務。
Constraints constraints = new Constraints.Builder().setRequiresCharging(true).setRequiredNetworkType(NetworkType.CONNECTED).setRequiresBatteryNotLow(true).build();
  • 將該Constraints設置到WorkRequest。WorkRequest是一個抽象類,它有兩種實現,OneTimeWorkRequestPeriodicWorkRequest,分別對應的是一次性任務和周期性任務。
OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadLogWorker.class).setConstraints(constraints)//設置觸發條件.build();
  • 設置延遲執行任務。假設你沒有設置觸發條件,或者當你設置的觸發條件符合系統的執行要求,此時,系統有可能立刻執行該任務,但如果你希望能夠延遲執行,那么可以通過setInitialDelay()方法,延后任務的執行。
OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadLogWorker.class).setInitialDelay(10, TimeUnit.SECONDS)//符合觸發條件后,延遲10秒執行.build();
  • 設置指數退避策略。假如Worker線程的執行出現了異常,比如服務器宕機,那么你可能希望過一段時間,重試該任務。那么你可以在Worker的doWork()方法中返回Result.retry(),系統會有默認的指數退避策略來幫你重試任務,你也可以通過setBackoffCriteria()方法,自定義指數退避策略。
OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadLogWorker.class)).setBackoffCriteria(BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS)//設置指數退避算法.build();
  • 為任務設置Tag標簽。設置Tag后,你就可以通過該抱歉跟蹤任務的狀態WorkManager.getWorkInfosByTagLiveData(String tag)或者取消任務WorkManager.cancelAllWorkByTag(String tag)。
OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadLogWorker.class).addTag("UploadTag").build();

4.將任務提交給系統。WorkManager.enqueue()方法會將你配置好的WorkRequest交給系統來執行。

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

5.觀察任務的狀態。

任務在提交給系統后,通過WorkInfo獲知任務的狀態,WorkInfo包含了任務的id,tag,以及Worker對象傳遞過來的outputData,以及任務當前的狀態。有三種方式可以得到WorkInfo對象。

WorkManager.getWorkInfosByTag()

WorkManager.getWorkInfoById()

WorkManager.getWorkInfosForUniqueWork()

如果你希望能夠實時獲知任務的狀態。這三個方法還有對應的LiveData方法。

WorkManager.getWorkInfosByTagLiveData()

WorkManager.getWorkInfoByIdLiveData()

WorkManager.getWorkInfosForUniqueWorkLiveData()

通過LiveData,我們便可以在任務狀態發生變化的時候,收到通知。

WorkManager.getInstance(this).getWorkInfoByIdLiveData(uploadWorkRequest.getId()).observe(MainActivity.this, new Observer<WorkInfo>() {@Overridepublic void onChanged(WorkInfo workInfo){Log.d("onChanged()->", "workInfo:"+workInfo);} });

6.取消任務。與觀察任務類似的,我們也可以根據Id或者Tag取消某個任務,或者取消所有任務。

WorkManager.getInstance(MainActivity.this).cancelAllWork();

7.WorkManager和Worker之間的參數傳遞。數據的傳遞通過Data對象來完成。

WorkManager通過setInputData()方法向Worker傳遞數據。

Data inputData = new Data.Builder().putString("input_data", "Hello World!").build();OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadLogWorker.class).setInputData(inputData).build();

Worker中接收數據,并在任務執行完成后,向WorkManager傳遞數據。

@Override public Result doWork() {//接收外面傳遞進來的數據String inputData = getInputData().getString("input_data");// 任務執行完成后返回數據Data outputData = new Data.Builder().putString("output_data", "Task Success!").build();return Result.success(outputData); }

WorkManager通過LiveDataWorkInfo.getOutputData(),得到從Worker傳遞過來的數據。

WorkManager.getInstance(this).getWorkInfoByIdLiveData(uploadWorkRequest.getId()).observe(MainActivity.this, new Observer<WorkInfo>() {@Overridepublic void onChanged(WorkInfo workInfo){if (workInfo != null && workInfo.getState() == WorkInfo.State.SUCCEEDED){String outputData = workInfo.getOutputData().getString("output_data");}} }); 注意:Data只能用于傳遞一些小的基本類型數據,且數據最大不能超過10kb。

8.周期任務PeriodicWorkRequest。前面提到過,WorkRequest的兩種實現OneTimeWorkRequest和PeriodicWorkRequest,分別對應的是一次性任務和周期性任務。一次性任務,即任務在成功完成后,便徹底結束。而周期性任務則會按照設定的時間定期執行。二者使用起來沒有太大差別。

需要注意的是:周期性任務的間隔時間不能小于15分鐘

PeriodicWorkRequest uploadWorkRequest = new PeriodicWorkRequest.Builder(UploadLogWorker.class, 15, TimeUnit.MINUTES).setConstraints(constraints).addTag(TAG).build();

9.任務鏈。如果你有一系列的任務需要順序執行,那么可以利用WorkManager.beginWith().then().then()...enqueue()方法。例如:我們在上傳數據之前,需要先對數據進行壓縮。

WorkManager.getInstance(this).beginWith(compressWorkRequest).then(uploadWorkRequest).enqueue();

假設在上傳數據之前,除了壓縮數據,還需要更新本地數據。壓縮與更新本地數據二者沒有順序,但與上傳數據存在先后順序。

WorkManager.getInstance(this).beginWith(compressWorkRequest, updateLocalWorkRequest).then(uploadWorkRequest).enqueue();

假設有更復雜的任務鏈,你還可以考慮使用WorkContinuation.combine()方法,將任務鏈組合起來。

WorkContinuation workContinuation1 = WorkManager.getInstance(this).beginWith(WorkRequestA).then(WorkRequestB); WorkContinuation workContinuation2 = WorkManager.getInstance(this).beginWith(WorkRequestC).then(WorkRequestD); List<WorkContinuation> taskList = new ArrayList<>(); taskList.add(workContinuation1); taskList.add(workContinuation2); WorkContinuation.combine(taskList).then(WorkRequestE).enqueue();

采用WorkContinuation.combine()的任務鏈執行順序

源代碼:https://github.com/Pangu-Immortal/Jetpack-demos

總結

開發者經常需要處理后臺任務,如果處理后臺任務所采用的API沒有被正確使用,那么很可能會消耗大量設備的電量。Android出于設備電量的考慮,為開發者提供了WorkManager,旨在將一些不需要及時完成的任務交給它來完成。雖然WorkManager宣稱,能夠保證任務得到執行,但我在真實設備中,發現應用程序徹底退出與重啟設備,任務都沒有再次執行。查閱了相關資料,發現這應該與系統有關系。我們前面也提到了,WorkManager會根據系統的版本,決定采用JobScheduler或是AlarmManager+Broadcast Receivers來完成任務。但是這些API很可能會受到OEM系統的影響。比如,假設某個系統不允許AlarmManager自動喚起,那么WorkManager很可能就無法正常使用。

而后我在模擬器中進行測試,模擬器采用的是Google原生系統,發現無論是徹底退出應用程序,或是重啟設備,任務都能夠被執行。所以,WorkManager在真實設備中不能正常使用,很可能就是系統的問題。因此,開發者在使用WorkManager作為解決方案時,一定要慎重。

另外,我還發現,周期任務的實際執行,與所設定的時間差別較大。執行時間看起來并沒有太明顯的規律。并且在任務執行完成后,WorkInfo并不會收到Success的通知。查閱了相關資料,發現Android認為Success和Failure都屬于終止類的通知。意思是,如果發出這類通知,則表明任務徹底結束,而周期任務不會徹底終止,會一直執行下去,所以我們在使用LiveData觀察周期任務時,不會收到Success這類的通知。這也是我們需要注意的地方。

總結

以上是生活随笔為你收集整理的Jetpack WorkManager的使用-完全解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。