6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Android] WorkerへDIする

Last updated at Posted at 2019-07-13

はじめに

JetPakckのWorkerへDI(コンストラクタインジェクション)する方法を日本語で解説している物がなかったのでメモ
※Qiita初投稿なので、稚拙なところや間違いはどんどんまさかりを投げていただけると嬉しいです。

問題点

WorkerはAndroidフレームワークがインスタンスの生成を行うため、デフォルトではContextとWorkerParametersしか受け取ることができない

val workManager = WorkManager.getInstance()
workManager.enqueue(OneTimeWorkRequest.from(LoggerWorker::class.java))

class LoggerWorker (ctx: Context,params: WorkerParameters) : Worker(ctx, params) {
    override fun doWork(): Result {
        Log.i(this.javaClass.simpleName,"ログが出力されています")
        return Result.success()
    }
}


解決方法

WorkerFactoryを使う
https://developer.android.com/reference/androidx/work/WorkerFactory

Workerを生成するときに呼び出される、WorkerFactoryを上書きすることで、workerへDIできるようになる

実装方法

例として、Android標準のLogをラップしただけのMyLoggerをLoggerWorkerへDIします。

MyLogger.kt
class MyLogger {
     fun log(tag:String,message:String){ |
         Log.i(tag,message) |
     } 
}
LoggerWorker.kt
 class LoggerWorker ( 
     ctx: Context, 
     params: WorkerParameters, 
     private val logger: MyLogger 
){}

1.WorkerFactoryを継承したMyWorkerFactoryを作成します。
createWorkerで生成したいWorkerのクラス名が渡ってくるので、それに基づいてWorkerのインスタンスを返します。

MyWorkerFactory

class MyWorkerFactory : WorkerFactory() {
    override fun createWorker(
        appContext: Context,
        workerClassName: String,
        workerParameters: WorkerParameters
    ): ListenableWorker? {
        return when (Class.forName(workerClassName)) {
            LoggerWorker::class.java -> LoggerWorker(appContext, workerParameters, MyLogger())
            else -> throw IllegalArgumentException("unknown worker class name: $workerClassName")
        }
    }
}

2.作成したMyWorkerFactoryをアプリケーションクラスを作成しWorkManager.initialize()メソッド経由でWorkerManagerへ登録します。(アプリケーションクラスのマニュフェストへの登録を忘れずに。)

MyApplication.kt
class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        WorkManager.initialize(this, Configuration.Builder().setWorkerFactory(MyWorkerFactory()).build())
    }

}

3.WorkerManagerはWorkerManager.initialize()で一度しか初期化できず、デフォルトでは自動的に初期化されるため、これを無効化します。

AndroidManifest.xml
<manifest >
    <application>
        <provider
                android:name="androidx.work.impl.WorkManagerInitializer"
                android:authorities="${applicationId}.workmanager-init"
                android:exported="false"
                tools:node="remove"/>
    </application>
</manifest>

4.ここままで準備は完了のため、あとは今まで通り呼び出します。

MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val workManager = WorkManager.getInstance()
        workManager.enqueue(OneTimeWorkRequest.from(LoggerWorker::class.java))
    }
}

コード全体

https://github.com/Cespresso/DaggerDIToWorker/tree/dont_use_dagger

WorkerへのDIをDaggerを使う前提で作成したものを流用しているので、masterブランチはdaggerを使ったパターンの物があります。
daggerのViewModelProvider.Factry等でよく使われているマルチバインディング等でいい感じ()になってます。そのうちこちらにまとめるかもしれませんが、参考の一番上の記事を元に実装したので気になる方は、そちらを参考にしてみてください。

参考

https://proandroiddev.com/dagger-2-setup-with-workmanager-a-complete-step-by-step-guild-bb9f474bde37

https://developer.android.com/reference/androidx/work/WorkManager

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?