【Android】WorkerFactoryをDaggerでDIする
経緯
プロダクトで定期的に実行する機能の開発があり、Workerというものを採用することになりました
その際にいくつか詰まったところがあったので、使い方や使用感をまとめたいと思います
Workerとは
困ったところ
WorkerはWorkManagerというAndroidフレームワークによって生成されます
その際にコンストラクタで受け取れる引数はContextとWorkerParametersのみで、他のオブジェクトを受け取ることはできません
それを実現するためには、独自のWorkerFactoryを作り、WorkManagerに渡してあげる必要があります
手順
- Workerを作成する
今回は独自のLogユースケースクラスを引数に取るWorkerを作ります
class LogWorker(
context: Context,
params: WorkerParameters,
private val logUseCase: LogUseCase
) : Worker(context, params) {
override fun doWork(): Result {
logUseCase.start()
return Result.success()
}
}
- WorkerFactoryを継承したLogFactoryを作成
class LogWorkerFactory(
private val logUseCase: LogUseCase
) : WorkerFactory() {
override fun createWorker(
appContext: Context,
workerClassName: String,
workerParameters: WorkerParameters
): ListenableWorker? {
return if (workerClassName == LogWorker::class.java.name){
LogWorker(appContext, workerParameters, logUseCase)
} else {
null
}
}
}
- 作成したLogWorkerFactoryを呼び出したいクラスからWorkManager.initialize()メソッド経由でWorkerManagerへ登録
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
WorkManager.initialize(
this,
Configuration.Builder().setWorkerFactory(LogWorkerFactory())
.build()
)
}
}
- デフォルトのWorkManagerInitializerを削除する旨をマニフェストファイルに記載
<manifest ...>
<application
...>
...
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:ignore="ExportedContentProvider"
tools:node="remove" />
</application>
</manifest>
- 通常通り呼び出しを行う()
今回は定期実行ということでPeriodicWorkRequestクラスを利用します
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val workManager = WorkManager.getInstance()
val logPeriodicWorkRequest = PeriodicWorkRequest.Builder(
LogWorker::class.java,
Duration.ofMinutes(15)
).build()
val operation = workerManager.enqueue(logPeriodicWorkRequest)
workManager.enqueue(OneTimeWorkRequest.from(LogWorker::class.java))
}
}
通常はここで終わりなんですが、プロダクトではDaggerを使っているので、provide メソッドによる管理を行いたいと思います
WorkerをDIしようとすると結構な手順が必要になるので、今回はWorkerではなく、WorkerFactoryのみDIしたいと思います
WorkerごとDIしたい場合は下記を参照
手順は簡単です
- provideメソッドをモジュールにセット
@Provides
@Singleton
fun provideWorkerFactory(
logUseCase: LogUseCase
): WorkerFactory {
return LogFactory(logUseCase)
}
- 呼び出しもとでInjectする
class MainActivity : AppCompatActivity() {
@Inject
lateinit var workerFactory: WorkerFactory
override fun onCreate(savedInstanceState: Bundle?) {
(省略)
}
}
まとめ
今回はDagger環境でWorkerを使う方法について解説しました
定期実行したいという際にまず出てくるのがWorkerという選択肢だと思うので、今後も使う機会があるのではないでしょうか
今回参考にさせていただいたページは下記です
今回も最後まで読んでいただいてありがとうございました
https://proandroiddev.com/dagger-2-setup-with-workmanager-a-complete-step-by-step-guild-bb9f474bde37