Studyplus Engineering Blog

スタディプラスの開発者が発信するブログ

WorkManager + Dagger2によるバックグラウンド処理

こんにちは、Androidチームの若宮(id:D_R_1009)です。 昨年末にAndroidチームが導入した、WorkManagerをDagger2と組み合わせる方法を紹介します。

WorkManagerとは

developer.android.com

WorkManagerは、確実に実行したい非同期処理に対して利用するAndroid Architecture Componentsとなります。 概要についてはDroidKaigi 2019の「実践 WorkManager」をご一読ください。

speakerdeck.com

また、CodeLabも用意されています。

codelabs.developers.google.com

WorkManager + Dagger2(DI)

StudyplusのAndroidアプリではDagger2を活用しているため、WorkManagerとDagger2を組み合わせる必要があります。 検索してみると、次の記事で組み合わせ方が紹介されていました。

proandroiddev.com

もともとAssistedInjectを利用していたこともあり、おおよそこの方法で導入することはできそうでした。 ただ、できれはWorkManagerも provide メソッドによる管理を行いたくなります。

と言うことで、対応していきます。

provide 対応

WorkManagerはインスタンス化する処理が(特に指定しなければ)デフォルトのものが利用されるため、この処理を切り替える必要があります。 対応したのがWorkManager 2.1のため、ドキュメントに従って AndroidManifest.xml に記述を加えます。

developer.android.com

この対応により、 WorkManager.getInscance(context) する前に Configuration.Provider をセットすることができます。

@Provides
@Singleton
fun provideWorkManager(
    context: Context,
    factory: WorkManagerFactory
): WorkManager {
    WorkManager.initialize(context, Configuration.Builder().setWorkerFactory(factory).build())

    return WorkManager.getInstance(context)
}

あとは記事の通り、諸々のモジュールをセットすれば完了です。

@Module(includes = [PresenterModule::class, WorkerBindingModule::class])
object WorkManagerModule {

    @Provides
    @Singleton
    fun provideWorkManager(
        context: Context,
        factory: WorkManagerFactory
    ): WorkManager
}

@Module(includes = [AssistedInject_PresenterModule::class])
@AssistedModule
internal interface PresenterModule

@MapKey
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class WorkerKey(val value: KClass<out ListenableWorker>)

@Module
interface WorkerBindingModule {
    @Binds
    @IntoMap
    @WorkerKey(HogeWorker::class)
    fun bindHogeWorker(factory: HogeWorker.Factory): ChildWorkerFactory
}

利用状況、所感

StudyplusのAndroidアプリでは、WorkManagerをRepository層とViewModel層の間にある概念として利用しています。 このため、DIによりViewModel層からWorkManagerを呼び出し、WorkManagerのWokerにRepositoryをInjectして非同期処理を実行する構成となります。

アプリケーションの各種ライフサイクルに影響を受けずに非同期処理を実行することができ、開発のしやすさが高まったと感じています。 アーキテクチャとしてMVVMを採用しているチームにおいては、有用な選択肢となるのではないでしょうか。

終わりに

簡単ではありますがWorkManagerとDagger2を組み合わせる方法の紹介と、その効果をまとめてみました。 WorkManagerはKotlin Coroutinesを利用することができるため、Repositoryの各メソッドをsuspend関数にしておくだけで、簡単に呼び出すことができます。

2020年も引き続き、よろしくお願いいたします。