phicdy devlog

Androidアプリ開発やその他技術系の記事をたまに書きます

AndroidとかiOSとかモバイル多め。その他技術的なことも書いていきます。

WorkManagerでWorkerを一意に実行して画面が死んでも復帰する

最近WorkManagerを使ってて少し嵌ったので書く。

環境

  • WorkManager 2.2.0
    • 最新はappcompat 1.1.0に依存していて問題がちらほらあるので使わない

Workerを一意に実行する

Workerを一意に実行するにはWorkManagerのbeginUniqueWorkを使う。WorkContinuationからはできないので注意。第一引数に一意にするための名前を指定する。後に実行結果のLiveDataを取り直すときに同じ名前を使う。第二引数にはExistingWorkPolicy.KEEPを指定する。KEEPにすることで何度呼んでも実行中であれば再実行されることはない。第三引数には最初に実行するWorkerを指定する。一つでもいいしListも渡せる。

val firstWork = OneTimeWorkRequestBuilder<FirstWorker>().build()
val second1Work = OneTimeWorkRequestBuilder<Second1Worker>().build()
val second2Work = OneTimeWorkRequestBuilder<FirstWorker>().build()

val uniqueName = "unique"
WorkManager.getInstance(context)
        .beginUniqueWork(uniqueName, ExistingWorkPolicy.KEEP, firstWork)
        .then(listOf(second1Work, second2Work))
        .enqueue()

画面が死んでも再observeできるLiveDataを返す

実行結果のLiveDataを返すときはenqueue()の返り値のWorkContinuationのworkInfoLiveDataではなくWorkManagerのgetWorkInfosForUniqueWorkLiveData(uniqueName)を使う。workInfoLiveDataだと初回は値が通知されるLiveDataが返るが実行中に再度呼ぶと通知されない。恐らく再度呼ばれた際に実行されたWorkerはないということで通知されないと考えられる。

return workManager.getWorkInfosForUniqueWorkLiveData(uniqueName)

あとはこのLiveDataをobserveするだけで画面が死んでも再度uniqueNameを起点にLiveDataを取り直して進捗を通知できる。