Android WorkManager使用入門

AnRFDev發表於2021-08-19

WorkManager使用入門

WorkManager提供了任務排程功能,我們可以對工作進行標記或命名。
我們用一個示例來演示如何使用WorkManager。本文使用Kotlin。

入門示例

gradle引入依賴

將以下依賴項新增到應用模組的build.gradle檔案中

dependencies {
    def work_version = "2.5.0"

    // (Java only)
    implementation "androidx.work:work-runtime:$work_version"

    // Kotlin + coroutines
    implementation "androidx.work:work-runtime-ktx:$work_version"

    // optional - RxJava2 support
    implementation "androidx.work:work-rxjava2:$work_version"

    // optional - GCMNetworkManager support
    implementation "androidx.work:work-gcm:$work_version"

    // optional - Test helpers
    androidTestImplementation "androidx.work:work-testing:$work_version"

    // optional - Multiprocess support
    implementation "androidx.work:work-multiprocess:$work_version"
}

新增依賴項並同步 Gradle 後,下一步要定義一些工作。

定義工作

這裡的工作為方便測試進行了簡化。實際專案中請改為具體的業務程式碼。
新建UploadWorker類繼承Worker類。需要2個引數context: Context, params: WorkerParameters
doWork()方法中是我們的具體任務,在WorkManager提供的後臺執行緒上非同步執行。

class UploadWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
    override fun doWork(): Result {
        for (i in 1..3) {
            Log.d(TAG, "模擬執行任務 ${tags.first()} ${Thread.currentThread()}")
            Thread.sleep(100) // 模擬耗時
        }
        return Result.success()
    }
}

doWork()方法中我們列印當前執行緒資訊。後面看看執行緒執行情況。

任務執行完畢,doWork()需要返回一個Result

  • Result.success():工作成功完成
  • Result.failure():工作失敗
  • Result.retry():工作失敗,應根據其重試政策在其他時間嘗試

建立 WorkRequest

前面我們定義好了工作類UploadWorkerWorkManager可以排程工作,讓工作執行起來。工作可以在某個時間段內定期執行,也可以只執行一次。
要執行工作,涉及到WorkRequest類和它的子類。

這裡我們演示只執行1次的工作,使用OneTimeWorkRequest
建立workA,作為一個Activity裡的變數

private val mWorkA = OneTimeWorkRequest.Builder(UploadWorker::class.java)
        .addTag("workA").build()

建立workB

val workB = OneTimeWorkRequest.Builder(UploadWorker::class.java)
        .addTag("workB").build()

將WorkRequest提交給WorkManager

使用enqueue方法將WorkRequest提交給WorkManager。

獲取WorkManager的例項用WorkManager.getInstance(applicationContext)方法。

mWorkA是變數

WorkManager.getInstance(applicationContext).enqueue(mWorkA)
// ...

workB是每次都新建一個物件,然後交給WorkManager去執行。

val workB = OneTimeWorkRequest.Builder(UploadWorker::class.java)
        .addTag("workB").build()
WorkManager.getInstance(applicationContext).enqueue(workB)

執行工作器的確切時間取決於WorkRequest中使用的約束和系統優化方式。
Google官方設計過WorkManager,能夠在滿足約束的情況下提供最佳行為。

執行測試

按鈕A觸發mWorkA,按鈕B觸發workB。分別點選按鈕A/B

模擬執行任務 workA Thread[pool-2-thread-3,5,main]
模擬執行任務 workA Thread[pool-2-thread-3,5,main]
模擬執行任務 workA Thread[pool-2-thread-3,5,main]
點選按鈕B Thread[main,5,main]
模擬執行任務 workB Thread[pool-2-thread-1,5,main]
模擬執行任務 workB Thread[pool-2-thread-1,5,main]
模擬執行任務 workB Thread[pool-2-thread-1,5,main]

觀察log發現,工作的doWork()方法在WorkManager提供的後臺執行緒上非同步執行。
主執行緒是[main,5,main],工作的執行緒是[pool-2-thread-3,5,main]

而在實際操作中發現,多次點選按鈕A,mWorkA只會執行第一次。後面再點選按鈕A,mWorkA也不會執行了。

小結

這個例子介紹瞭如何引入WorkManager,定義工作(任務),排隊執行任務。
在使用方式上,讓人聯想到AsyncTask

其他參考

相關文章