WorkManager工作約束,延遲與查詢工作
本文可能會混用“工作”與“任務”這兩個詞。
本文例子使用Kotlin
準備一個工作類(任務)UploadWorker2
class UploadWorker2(context: Context, params: WorkerParameters) : Worker(context, params) {
override fun doWork(): Result {
Log.d(TAG, "模擬執行任務2 ${Thread.currentThread()}")
return Result.success()
}
}
工作約束
約束可讓工作延遲到滿足最佳條件時執行。下面的約束適用於 WorkManager。
名稱 | 說明 |
---|---|
NetworkType | 約束執行工作所需的網路型別。例如 Wi-Fi (UNMETERED)。 |
BatteryNotLow | 若為 true,那麼當裝置處於“電量不足模式”時,工作不會執行。 |
RequiresCharging | 若為 true,那麼工作只能在裝置充電時執行。 |
DeviceIdle | 若為 true,則裝置必須處於空閒狀態才能執行工作。如果考慮到其他應用的效能,建議用這個約束。 |
StorageNotLow | 若為 true,那麼當裝置上的儲存空間不足時,工作不會執行。 |
可用Constraints.Builder()
來建立工作約束。然後將Constraints例項分配給WorkRequest.Builder()
。
也就是說,工作約束是針對工作WorkRequest的。
下面這個工作約束,只有1個要求,在裝置使用計費流量是執行任務。
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.METERED)
.build()
val d1 = OneTimeWorkRequest.Builder(UploadWorker2::class.java)
.setConstraints(constraints)
.addTag("約束").build()
mIdList.add(d1.id) // 登記任務id,可去掉
WorkManager.getInstance(applicationContext).enqueue(d1)
真機測試中,如果一開始手機用著wifi,那麼任務不會執行。而關掉wifi,開啟流量開關,就會執行任務。
這就是滿足最佳條件時執行。
NetworkType說明
androidx.work.NetworkType
是一個列舉類。目前有
列舉 | 說明 |
---|---|
NOT_REQUIRED | 這個工作不需要網路 |
CONNECTED | 這個工作需要有網路連線 |
UNMETERED | 需要Wi-Fi |
NOT_ROAMING | 非漫遊網路 |
METERED | 需要按流量計費的網路 |
延遲工作
如果工作沒有約束,或者當工作加入佇列時所有約束都得到了滿足,那麼系統可能會選擇立即執行該工作。
如果不希望工作立即執行,可以給工作設定一個延遲時間。
下面這個工作是要延遲3秒鐘。
val d1 = OneTimeWorkRequest.Builder(UploadWorker2::class.java)
.addTag("延遲1")
.setInitialDelay(3, TimeUnit.SECONDS)
.build()
WorkManager.getInstance(applicationContext).enqueue(d1)
enqueue
任務後,查一下任務狀態。工作從ENQUEUED
狀態,執行完畢後變成了SUCCEEDED
。
WorkInfo{mId='2794b4dd-7c02-4fd0-9851-8798a0da3bb2', mState=ENQUEUED, mOutputData=Data {}, mTags=[com.rustfisher.tutorial2020.workmanaer.WorkManagerAct$UploadWorker2, 延遲1], mProgress=Data {}}
WorkInfo{mId='2794b4dd-7c02-4fd0-9851-8798a0da3bb2', mState=SUCCEEDED, mOutputData=Data {}, mTags=[com.rustfisher.tutorial2020.workmanaer.WorkManagerAct$UploadWorker2, 延遲1], mProgress=Data {}}
查詢工作
使用UUID查詢
新建工作的時候,系統會分配一個UUID。我們可以記錄UUID到mIdList
裡。通過UUID可以查詢到工作當前的狀態。
val mgr = WorkManager.getInstance(applicationContext)
for (id in mIdList) {
val cur = mgr.getWorkInfoById(id)
Log.d(TAG, "查詢任務 ${cur.get()}")
}
一個工作狀態的例子,狀態是ENQUEUED
WorkInfo{mId='16cc292d-f140-488f-9ab5-a0d22b95d128', mState=ENQUEUED, mOutputData=Data {}, mTags=[com.rustfisher.tutorial2020.workmanaer.WorkManagerAct$UploadWorker, r1], mProgress=Data {}}
使用tag查詢
前面我們給工作打上tag。可以用WorkManager的getWorkInfosByTag()
方法把指定tag的工作查出來。
val mgr = WorkManager.getInstance(applicationContext)
for (w in mgr.getWorkInfosByTag("約束1").get()) {
Log.d(TAG, "$w")
}
工作狀態的例子,下面這個工作UploadWorker
狀態是SUCCEEDED
,tag裡有約束1
WorkInfo{mId='fed1974c-77e5-46ba-8b38-f6c01d68fe4c', mState=SUCCEEDED, mOutputData=Data {}, mTags=[com.rustfisher.tutorial2020.workmanaer.WorkManagerAct$UploadWorker, 約束1], mProgress=Data {}}
需要注意的是,工作的狀態是儲存起來的。即使重啟app或者手機,都可以查到這個工作的狀態。
假設查詢tag是約束1
,我們能得到之前建立的含有這個約束1
標籤的工作。