Android WorkManager工作約束,延遲與查詢工作

AnRFDev發表於2021-08-23

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。可以用WorkManagergetWorkInfosByTag()方法把指定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標籤的工作。

參考

相關文章