iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 29
1
Mobile Development

Android Architecture Components 學習心得筆記系列 第 29

Day 29 WorkManager (Last) 進階用法與總結

上一篇完成了最基本的使用,僅僅是開了另一個執行緒去執行背景任務,看起來沒什麼特別的,來看看 WorkManager 有什麼特別的地方。

約束條件

val constraints = Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED)  // 網路狀態
        .setRequiresBatteryNotLow(true)                 // 是否在電量不足時執行
        .setRequiresCharging(true)                      // 是否在充電時執行
        .setRequiresStorageNotLow(true)                 // 是否在儲存空間不足時執行
        .setRequiresDeviceIdle(true)                    // 是否在待機狀態執行
        .build()
        
val request = OneTimeWorkRequest.Builder(MainWorker::class.java)
        .setConstraints(constraints)
        .build()

除了網路狀態,其他的條件都是傳入一個布林值,網路狀態還有其他的選項可以選:

狀態 說明
CONNECTED 網路連接
NOT_REQUIRED 沒有要求
UNMETERED 連接無限流量的網路
METERED 連接有限流量的網路
NOT_ROAMING 連接非漫遊的網路

定時任務

OneTimeWorkRequest 是指只執行一次的任務,要執行多次的任務就必須用到 PeriodicWorkRequest

val request = PeriodicWorkRequest
        .Builder(MainWorker::class.java, 15, TimeUnit.MINUTES)
        .setConstraints(constraints)
        .setInputData(data)
        .build()

這是一個每隔 15 分鐘就執行一次的任務,PeriodicWorkRequest
最短限制就是 15 分鐘不能再少

任務隊列

WorkManager 允許我們把多個任務進行排程,像一個隊伍一樣,並按照想要的順序執行。

WorkManager.getInstance()
        .beginWith(workA)
        .then(workB)
        .then(workC)
        .enqueue()

從 workA 開始執行,並依序執行 workB, workC,上一個 work 的 outputData 便成為下一個 work 的 intputData。

WorkManager.getInstance()
        .beginWith(workA, workB)
        .then(workC)
        .enqueue()

workA, workB 同時執行,執行完再執行 workC

還可以組成任務鍊(chain)

val chain1 = WorkManager.getInstance()
        .beginWith(workA)
        .then(workB)
        
val chain2 = WorkManager.getInstance()
        .beginWith(workC)
        .then(workD)
        
val chain3 = WorkContinuation
        .combine(chain1, chain2)
        .then(workE)
        
chain3.enqueue()

chain1 是一個先執行 workA 再執行 workB 的任務鍊
chain2 是一個先執行 workC 再執行 workD 的任務鍊

最後 chain1, chain2 執行完後在執行 workE。

任務唯一性

我們希望在任務隊列裡面,同一個任務只存在一個,避免任務的重複執行,這時候就可以用到 beginUniqueWork

WorkManager.getInstance()
        .beginUniqueWork("unique", ExistingWorkPolicy.REPLACE, request)
        .enqueue()

傳入一個任務的 TAG, 還有任務的執行方法,可替換如下:

狀態 說明
REPLACE 如果任務隊列裡有一樣 TAG 的任務,取消並刪除這個任務,並新增一個任務進隊列裡面
APPEND 加入任務隊列的末端
KEEP 如果任務隊列裡有一樣 TAG 的任務,就什麼都不做,不然就新增一個任務進隊列裡面

WorkManager 小結

WorkManager 算是一個把各個類別的分工做得很清楚的組件,對於每個類別的各個方法的可讀性很高,算是很好入門,而且幾乎兼容各個 API 版本的問題,開發者只要專心處理想要執行的任務,不必再為了 api 版本操心。
現在如果想要執行背景任務不管是因應哪種需求,WorkManager 將是未來的不二之選

其他有任何問題或講得不清楚的地方歡迎留言和我討論。

更歡迎留言糾正我任何說錯的地方!

下一篇:Architecture Components 總結 + 30天完賽心得


上一篇
Day 28 WorkManager (一) 介紹與基本使用
下一篇
Day 30 完賽總結與心得
系列文
Android Architecture Components 學習心得筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
wow5109
iT邦新手 5 級 ‧ 2021-03-16 17:21:58

請問WorkManager在背景執行會有延遲執行的問題嗎?(指的是被系統延後,而非自己設定的發送時間)謝謝。

我要留言

立即登入留言