Android使用Kotlin API實踐WorkManager
WorkManager 提供了一系列 API 可以更加便捷地規劃異步任務,即使在應用被關閉之后或者設備重啟之后,仍然需要保證立即執行的或者推遲執行的任務被正常處理。對于 Kotlin 開發者,WorkManager 為協程提供了最佳的支持。在本文中,我將通過實踐 WorkManager codelab 為大家展示 WorkManager 中與協程相關的基本操作。那么讓我們開始吧!
WorkManager 基礎當您需要某個任務保持運行狀態,即使用戶切換到別的界面或者用戶將應用切換到后臺,甚至設備重啟的時候仍然不影響任務狀態,那么非常推薦使用 WorkManager。類似的應用場景包括:
上傳日志或者報告數據 使用濾鏡處理圖片的同時保存圖片 通過網絡定期同步本地數據如果您的即時任務可以在用戶脫離某個作用域時結束,比如切換到其它界面,我們建議您還是直接使用 Kotlin 協程。
在這個 WorkManager codelab 教程中,我們會對圖片進行模糊化處理,并且將處理后的數據存儲在磁盤上。我們看一下這個過程中需要哪些操作。
添加 work-runtime-ktx 依賴:
// 獲取最新的版本號 https://developer.android.google.cn/jetpack/androidx/releases/workdef work_version = '2.5.0'implementation 'androidx.work:work-runtime-ktx:$work_version'
首先實現我們自己的 Worker 類。我們會在這里實現真正需要在后臺執行業務的代碼。您可以擴展 Worker 類,并且復寫 doWork() 方法。由于這個類非常重要,我們會在后邊內容中進行詳細介紹。這里是它最初的實現代碼。
/* Copyright 2020 Google LLC. SPDX-License-Identifier: Apache-2.0 */class BlurWorker(ctx: Context, params: WorkerParameters) : Worker(ctx, params) { override fun doWork(): Result {val resourceUri = inputData.getString(KEY_IMAGE_URI)return try { if (resourceUri.isNullOrEmpty()) {Timber.e('Invalid input uri')throw IllegalArgumentException('Invalid input uri') } val outputData = blurAndWriteImageToFile(resourceUri) Result.success(outputData)} catch (throwable: Throwable) { Timber.e(throwable, 'Error applying blur') Result.failure()} }…}
接下來,創建我們的 work 請求,在本例中,我們希望整個操作僅運行一次,所以我們使用 OneTimeWorkRequest.Builder,將需要模糊化處理的圖片的 Uri 作為參數傳入。
Kotlin 小貼士 : 要創建輸入數據,我們可以使用 workDataOf 函數,它會幫我們創建數據構建器,并且填充鍵值對,然后為我們創建數據。
/* Copyright 2020 Google LLC. SPDX-License-Identifier: Apache-2.0 */val blurBuilder = OneTimeWorkRequestBuilder<BlurWorker>()val data = workDataOf(KEY_IMAGE_URI to imageUri.toString())blurBuilder.setInputData(data)
我們使用 WorkManager 類將上面所做的工作添加到計劃隊列并且運行。我們可以提供需要執行的任務和這些任務的限制條件。
/* Copyright 2020 Google LLC. SPDX-License-Identifier: Apache-2.0 */val workManager = WorkManager.getInstance(application)val continuation = workManager.beginUniqueWork(blurBuilder.build())// 執行任務continuation.enqueue()使 Worker 開始執行任務
當您使用 Worker 的時候,WorkManager 會在后臺線程中自動調用 Worker.doWork()。doWork() 返回的 Result 會告知 WorkManager 服務是否成功,如果失敗則告知是否需要重試。
Worker.doWork() 屬于同步調用 -- 您的后臺操作需要以阻塞的方式執行,并且所有任務需要在整個 doWork() 函數結束的時候完成。如果您在 doWork() 里調用異步的 API 然后返回結果,那么您回調函數的執行可能會出現問題。
但是如果我希望進行異步操作怎么辦?我們來將上面的示例操作變得復雜一點,比如我希望在數據庫中存儲所有進行模糊化處理的文件的 Uri。
所以我創建了:
一個簡單的 BlurredImage 實體 一個用于插入和獲取圖片的 DAO 類 數據庫相關的實現代碼請 點擊這里。
如果您需要執行異步操作,比如在數據庫中存儲數據或者發起網絡請求,在 Kotlin 中,我們推薦使用 CoroutineWorker。
CoroutineWorker 通過使用 Kotlin 協程來執行異步任務。
doWork() 方法是一個 suspend 方法。也就是說我們這里可以調用可掛起的 dao 函數。
/* Copyright 2020 Google LLC. SPDX-License-Identifier: Apache-2.0 */class BlurWorker(ctx: Context, params: WorkerParameters) : CoroutineWorker(ctx, params) { override suspend fun doWork(): Result {val resourceUri = inputData.getString(KEY_IMAGE_URI)return try { if (resourceUri.isNullOrEmpty()) {Timber.e('Invalid input uri')throw IllegalArgumentException('Invalid input uri') } val outputData = blurAndWriteImageToFile(resourceUri) // 將 uri 存儲到數據庫 val imageDao = ImagesDatabase.getDatabase(applicationContext).blurredImageDao() imageDao.insert(BlurredImage(resourceUri)) Result.success(outputData)} catch (throwable: Throwable) { Timber.e(throwable, 'Error applying blur') Result.failure()} }...}
doWork() 默認使用 Dispatchers.Default。您可以將其替換為您所需的 Dispatcher。在這里,我們不需要這么做,因為 Room 已經將數據插入操作放在另外的 Dispatcher 中完成了。更多相關內容可以參考 Room Kotlin API。
開始使用 CoroutineWorker 來執行異步任務吧,即使用戶關閉應用也可以確保任務完成。
如果您希望了解更多關于 WorkManager 的內容,請關注未來的相關文章。在那之前,可以訪問我們的 codelab 和文檔:
WorkManager 文檔 Codelab | 使用 WorkManager Codelab | WorkManager 進階以上就是Android使用Kotlin API實踐WorkManager的詳細內容,更多關于Android實踐WorkManager的資料請關注好吧啦網其它相關文章!
相關文章:
