@HiltWorkerの使い方とエラー集
HiltWorkerの理解のためのメモです。遭遇すると思われるエラーも載せていますのでもしよかったら参考にしてください。
HiltWorkerとは
DI(依存関係の注入)を行うために使用します。基本的には公式サイトのやり方に沿えば問題ないと思います。
実践
興味があるので、公式サイトの方法で実装しながらちょっとずつ動かしてエラーを見たいと思います。
まずはコンストラクタに「@AssistedInject」、コンストラクタの中に「@Assisted」を付けただけで実行してみます。
@HiltWorker
class NotificationsWorker @AssistedInject constructor(
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters
): CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
Log.i("test", "test")
}
}
これは問題なく動きました。この二つはアノテーションで自動的にDIしてくれるようです。
次に「@Singleton」アノテーション済みのクラスをコンストラクタに指定して実行してみます。
@HiltWorker
class NotificationsWorker @AssistedInject constructor(
@Assisted appContext: Context,
@Assisted workerParams: WorkerParameters,
private val systemTrayNotifier: Notifier
): CoroutineWorker(appContext, workerParams) {
override suspend fun doWork(): Result {
systemTrayNotifier.function01()
}
}
次のようなエラーが表示されます。
Could not instantiate com.example.NotificationsWorker
java.lang.NoSuchMethodException: com.example.NotificationsWorker. [class android.content.Context, class androidx.work.WorkerParameters]
~~~
Could not create Worker com.example.NotificationsWorker
こちらを訳すと
「NotificationsWorkerクラスをインスタンス化できませんでした。
ContextとWorkerParametersをコンストラクタで指定しているNotificationsWorkerクラスは存在しません。」
になります。
ここからコンストラクタにクラスを加えただけでは、Hilt側では認識できず、ContextとWorkerParametersをコンストラクタに指定したNotificationsWorkerクラスを探してエラーを出力しているようです。
次は公式の方法に沿ってApplicationクラスでConfiguration.Providerを実装して動かしてみます。とりあえず公式からコピペして動かしてみました。
@HiltAndroidApp
class ExampleApplication : Application(), Configuration.Provider {
@Inject
lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
これは上と同じエラーが出力されました。
Could not instantiate com.example.NotificationsWorker
java.lang.NoSuchMethodException: com.example.NotificationsWorker. [class android.content.Context, class androidx.work.WorkerParameters]
~~~
Could not create Worker com.example.NotificationsWorker
まだ探しきれていないようです。次にmanifestにproviderを加えてみます。providerはapplicationタグの中に記述する必要があります。
</manifest>
</application>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove">
</provider>
</application>
</manifest>
今度は問題なく動きました。これはデフォルトのWorkManagerの構成を停止したことが原因のようです。
公式によると、WorkManagerはアプリの起動時に自動的に構成され、ほとんどのアプリに適した合理的なオプションが設定されるようです。要するに全てのアプリでWorkManagerは知らないうちに自動的に構成されています。
先ほどのApplicationクラスでConfiguration.Providerを実装するということはWorkManagerの構成をカスタマイズしたことになります。(こちらの最下部の星マークより)
そのため自動的に構成されるWorkManagerを停止することで、カスタマイズしたWorkManagerを使用できるようになると思われます。