こんにちは、Androidチームの若宮(id:D_R_1009)です。 昨年末にAndroidチームが導入した、WorkManagerをDagger2と組み合わせる方法を紹介します。
WorkManagerとは
WorkManagerは、確実に実行したい非同期処理に対して利用するAndroid Architecture Componentsとなります。 概要についてはDroidKaigi 2019の「実践 WorkManager」をご一読ください。
また、CodeLabも用意されています。
codelabs.developers.google.com
WorkManager + Dagger2(DI)
StudyplusのAndroidアプリではDagger2を活用しているため、WorkManagerとDagger2を組み合わせる必要があります。 検索してみると、次の記事で組み合わせ方が紹介されていました。
もともとAssistedInjectを利用していたこともあり、おおよそこの方法で導入することはできそうでした。
ただ、できれはWorkManagerも provide
メソッドによる管理を行いたくなります。
と言うことで、対応していきます。
provide
対応
WorkManagerはインスタンス化する処理が(特に指定しなければ)デフォルトのものが利用されるため、この処理を切り替える必要があります。
対応したのがWorkManager 2.1のため、ドキュメントに従って AndroidManifest.xml
に記述を加えます。
この対応により、 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年も引き続き、よろしくお願いいたします。