Jetpack之後臺任務——WorkManager

背景

公司自己寫的數據分析,額…希望每半小時上報一次。之前是用的Service,但在Android文檔關於內存優化部分提到使用完Service後要將其停止,像這種週期性任務功能上來說是肯定不能停的。而Jetpack剛剛好提供了後臺任務WorkManager,試着用它實現下。

WorkManager 簡介

先看它的使用場景

  • 向後端服務發送日誌或分析數據
  • 定期將應用數據與服務器同步

這個的使用場景與我的需求完全契合。

WorkManager使用

  1. 添加依賴
    def work_version = "2.3.1"
    implementation "androidx.work:work-runtime-ktx:$work_version"
    
    提示:可能會報以下錯誤
    Cannot inline bytecode built with JVM target 1.8 into bytecode that is being built with JVM target
    
    需要在gradle中加入下面代碼:
    android{
    	compileOptions {
            sourceCompatibility = '1.8'
            targetCompatibility = '1.8'
        }
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }
    
  2. 編寫後臺功能
    要使用WorkerManager管理後臺任務需要繼承 Worker 並在 doWork() 中編寫我們自己的後臺處理邏輯:
    class ReportWorker(val context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
        override fun doWork(): Result {
    		// TODO 後臺邏輯
            return Result.success()
        }
    }
    
    在後臺邏輯中我們可以編寫自己要執行的代碼,並可以根據實際情況返回Result.success()Result.failure()
  3. 啓動Worker
    // 一次性任務
    // val reportRequest = OneTimeWorkRequestBuilder<ReportWorker>().build()
    // 週期性任務
    val reportRequest = PeriodicWorkRequestBuilder<ReportWorker>(30, TimeUnit.MINUTES).build()
    WorkManager.getInstance().enqueue(reportRequest)
    
    啓動Worker非常簡單,只需要創建一個Worker,把它加入到WorkManager的執行隊列中就可以了。

WorkManager高級用法

  1. 添加Worker的約束條件
    有時我們的後臺任務需要連接網絡下執行,儘管我們在doWork()可以進行判斷,但WorkerManager爲我們提供了更便捷的方式:通過在創建Worker時添加 Constraints 來爲後臺任務添加執行時的約束條件。

    val constraints = Constraints.Builder()
                    .setRequiresCharging(true)
                    .setRequiredNetworkType(NetworkType.CONNECTED)
                    .build()
    val reportRequest = PeriodicWorkRequestBuilder<ReportWorker>(30, TimeUnit.MINUTES)
                      .setConstraints(constraints)
                      .build()
    WorkManager.getInstance().enqueue(reportRequest)
    

    Constraints爲我們提供了很多約束條件,例如:網絡狀態、電量是否充足、存儲空間是否充足等

  2. Worker 取消
    Worker的取消非常簡單,可以直接使用 WorkManager.cancelWorkById(UUID) 來實現,而在我們創建Worker時每個Worker都會有一個UUID。
    如果我們爲Woker設置了tag,也可以通過 WorkManager.cancelAllWorkByTag(String) 來取消Worker

  3. 唯一任務
    Worker如果不手動取消那麼它並不會隨應用的退出而自動終止,這樣當我們再次進入App執行到創建Worker的代碼時就會再次創建一個Worker。這種情況對於OneTimeWorkRequest是沒有什麼影響的,但對於PeriodicWorkRequest 會出現越來越多的Worker在WorkerManager中執行。本來半小時執行一次的任務可能因此執行了多次。當然我們可以在創建Worker前cancel掉上一個Worker,但這樣就不能保證切換過程中的執行週期。爲解決這個問題,我們需要使用enqueueUniqueWork來向WorkerManger中添加我們的Worker

    WorkManager.getInstance().enqueueUniquePeriodicWork("uniqueWorkName", ExistingPeriodicWorkPolicy.KEEP,reportRequest)
    

    其中:
    "uniqueWorkName" 爲唯一名稱,該名稱是後面添加策略的判斷標準,注意它與tag意義不同;
    KEEP 表示保持原有的Worker,忽略新創建的;除了KEEP,還可以使用 REPLACE 表示使用新的替換舊的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章