【Android】Hiltを使ってWorkerにDIする

## はじめに
[こちらの記事](https://qiita.com/Nkot117/items/e86c45c5236fcc28f926)（【Android】WorkManagerを使ってPUSH通知を飛ばす）では、Workerクラスを作成し、WorkManagerのOneTimeWorkRequestを使ってPUSH通知を飛ばす内容をまとめました。

今回はの上記で作成したWorkerに、Hiltを使って依存注入する方法をまとめたいと思います。

## Hiltとは何か
Androidアプリで依存性注入（Dependency Injection）を簡単に実装するためのライブラリになります。
依存性注入とは何か、どう嬉しいのか等はここでは特に触れません。
詳しくは[公式サイト](https://developer.android.com/training/dependency-injection/hilt-android?hl=ja&_gl=1*1czggd0*_up*MQ..*_ga*MTU1OTIyMDM4My4xNzE3NDk5NzIy*_ga_6HH9YJMN9M*MTcxNzQ5OTcyMi4xLjAuMTcxNzQ5OTcyMi4wLjAuMA..)を参照ください。

## 実装
### 依存関係の追加
まずPJレベルのgradleにプラグインを追加します。
```build.gradle.kts
plugins {
    id("com.google.dagger.hilt.android") version "2.48" apply false
}

```
次にアプリレベルのgradleに以下の依存関係を追加します。
主にHiltとHiltをWorkerに適用するための依存関係を追加します。
```build.gradle.kts
    val hiltVersion = "2.49"
    implementation "com.google.dagger:hilt-android:$hiltVersion"
    kapt "com.google.dagger:hilt-compiler:$hiltVersion"
    
    val hiltWorkVersion = "1.2.0"
    implementation "androidx.hilt:hilt-work:$hiltWorkVersion"
    kapt "androidx.hilt:hilt-compiler:$hiltWorkVersion"
  
}
```
### アプリケーションクラスの作成
Hiltを使うにはApplicationを継承したクラスを作成し、＠HiltAndroidAppのアノテーションをつける必要があります。
また、今回はWorkerにDIを行うためにHiltWorkerFactoryを定義します。
通常のWorkerを使う場合、WorkManagerが自動的にWorkerのインスタンスを生成しますが、その場合依存関係を注入する方法がありません。
WorkerFactoryを定義することで、Workerのインスタンス生成時にHiltで依存性注入を行えるようになります。
```PushNotificationApp.kt
@HiltAndroidApp
class PushNotificationApp : Application(), Configuration.Provider {
    @Inject
    lateinit var workerFactory: HiltWorkerFactory

    override val workManagerConfiguration: Configuration
        get() =  Configuration.Builder()
            .setWorkerFactory(workerFactory)
            .build()
}
```
### AndroidManifestの編集
Manifestファイルに先ほど作成したアプリケーションクラスを指定します。
また、WorkManagerのdefault initializerが走らないように、default initializerの無効化を行います。
無効化方法は2パターンあり、App Startupを使っているか否かで記載内容が異なります。
```AndroidManifest.xml
    <application
        android:name=".PushNotificationApp"
        ・・・
        >
        ・・・
        <!-- App Startupを使っていない場合の記載パターン -->
        <provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="${applicationId}.androidx-startup"
            tools:node="remove">
        </provider>

        <!-- App Startupを使っている場合の記載パターン -->
        <provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="${applicationId}.androidx-startup"
            android:exported="false"
            tools:node="merge">
        <meta-data
            android:name="androidx.work.WorkManagerInitializer"
            android:value="androidx.startup"
            tools:node="remove" />
</provider> 

```

一旦ここまででWorkerにDIする準備は完了です🎉

### WorkerにDIしてみる
[前回の記事](https://qiita.com/Nkot117/items/e86c45c5236fcc28f926)で作成したWorkerクラス(PushNotificationWorker)をもとに、DIを行いたいと思います。
内容としては通知を行う処理を別クラス(NotificationSender)に移し、別クラスをHiltを使ってWorkerにDIするという内容です。
（通知を行う処理については、前回の記事を参照ください。）
実際に実装したコードは以下になります。
```PushNotificationWorker.kt
@HiltWorker
class PushNotificationWorker  @AssistedInject constructor (
    @Assisted context: Context,
    @Assisted params: WorkerParameters,
    // 通知処理を持ったNotificationSenderをDI
    private val notificationSender: NotificationSender
) : Worker(context, params) {
    override fun doWork(): Result {
        notificationSender.sendPushNotification()
        return Result.success()
    }
}
```
所々、Hiltを使ったWorkerのDIを行うためのアノテーションがついています。

実装は以上になります。

## おわりに
今回はHilt使ってWorkerにDIする方法をざっくりまとめました。
このようにすることで、Workerに簡単にDIすることができ、またWorker自体のUnit Testも書きやすくなるかと思います。

前回の記事の続きになりましたが、どこか参考になるところがあれば幸いです！
## 参考
[【Android】WorkManagerを使ってPUSH通知を飛ばす](https://qiita.com/Nkot117/items/e86c45c5236fcc28f926)
[Hilt を使用した依存関係挿入](https://developer.android.com/training/dependency-injection/hilt-android?hl=ja&_gl=1*1czggd0*_up*MQ..*_ga*MTU1OTIyMDM4My4xNzE3NDk5NzIy*_ga_6HH9YJMN9M*MTcxNzQ5OTcyMi4xLjAuMTcxNzQ5OTcyMi4wLjAuMA..)
[HiltWorker](https://developer.android.com/reference/androidx/hilt/work/HiltWorker)
[WorkManager のカスタム構成と初期化](https://developer.android.com/develop/background-work/background-tasks/persistent/configuration/custom-configuration?authuser=1&hl=ja)