3

Hilt keeps not initializing the Worker just because of sharedPreferences variable here

@HiltWorker 
class AnilistNotificationWorker @AssistedInject constructor(     
    @Assisted private val context: Context,     
    @Assisted workerParams: WorkerParameters,     
    private val sharedPreferences: UserPreferencesRepository 
) : CoroutineWorker(appContext = context, params = workerParams) {
    override suspend fun doWork(): Result {
        println("executing worker")
        return Result.success()
    }
}
@HiltAndroidApp
class MyApplication : Application(), Configuration.Provider {
    @EntryPoint
    @InstallIn(SingletonComponent::class)
    interface HiltWorkerFactoryEntryPoint {
        fun hiltWorkerFactory(): HiltWorkerFactory
    }

    override fun onCreate() {
        super.onCreate()
        scheduleApiWorker()
    }

    // This is the correct and robust way to provide the configuration.
    override val workManagerConfiguration: Configuration
        get() = Configuration.Builder()
            .setWorkerFactory(
                // Use the EntryPoint to get the factory instance.
                EntryPointAccessors.fromApplication(this, HiltWorkerFactoryEntryPoint::class.java)
                    .hiltWorkerFactory()
            )
            .build()

    private fun scheduleApiWorker() {
        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

        println("Scheduling notification worker")

        // Use PeriodicWorkRequest for recurring work
        val notificationWorkRequest = OneTimeWorkRequestBuilder<AnilistNotificationWorker>()
            .setConstraints(constraints)
            .build()

        // Enqueue as unique periodic work
        WorkManager.getInstance(this).enqueue(
            notificationWorkRequest
        )
    }
}
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_preferences")

@Module @InstallIn(SingletonComponent::class) 
object DataStoreModule {
    @Provides
    @Singleton
    fun providesDataStore(@ApplicationContext context: Context): DataStore<Preferences> {
        return context.dataStore
    }
}
@Module
@InstallIn(SingletonComponent::class)
object RepositoryModule {
    @Provides
    @Singleton
    fun providesUserPreferencesRepository(dataStore: DataStore<Preferences>): UserPreferencesRepository {
        return UserPreferencesRepository(dataStore)
    }
}

@Singleton class UserPreferencesRepository (private val dataStore: DataStore<Preferences>)

provider inside my manifest file

<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>

my gradle files

:app module

plugins {
    // ...
    id("com.google.dagger.hilt.android") version "2.57.1" apply false//Important dependency
}

project module

plugins {
    // ...
    id("kotlin-kapt")
    id("com.google.dagger.hilt.android")
}

kapt {
    correctErrorTypes = true
}

dependencies {
    implementation(libs.androidx.hilt.common)//Important dependencies
    implementation(libs.hilt.android)//Important dependencies
    implementation(libs.androidx.work.runtime.ktx)//Important dependencies
    implementation(libs.androidx.hilt.work)//Important dependencies
    kapt(libs.hilt.android.compiler)//Important dependencies
    implementation(libs.androidx.datastore.preferences)
}

and these are the library versions

[versions]
datastorePreferences = "1.1.7"
hiltAndroid = "2.57.1"
workRuntimeKtx = "2.10.3"
hiltCommon = "1.2.0"
hiltWork = "1.2.0"

[libraries]
androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" }
hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" }
androidx-work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "workRuntimeKtx" }
androidx-hilt-common = { group = "androidx.hilt", name = "hilt-common", version.ref = "hiltCommon" }
androidx-hilt-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hiltWork" }

Here is the full stacktrace:

java.lang.NoSuchMethodException: com.example.myani.data.notification.AnilistNotificationWorker.<init> [class android.content.Context, class androidx.work.WorkerParameters]
    at java.lang.Class.getConstructor0(Class.java:3385)
    at java.lang.Class.getDeclaredConstructor(Class.java:3067)
    at androidx.work.WorkerFactory.createWorkerWithDefaultFallback$fallbackToReflection(WorkerFactory.kt:87)
    at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.kt:96)
    at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.kt:234)
    at androidx.work.impl.WorkerWrapper.access$runWorker(WorkerWrapper.kt:67)
    at androidx.work.impl.WorkerWrapper$launch$1$resolution$1.invokeSuspend(WorkerWrapper.kt:98)
    at androidx.work.impl.WorkerWrapper$launch$1$resolution$1.invoke(Unknown Source:8)
    at androidx.work.impl.WorkerWrapper$launch$1$resolution$1.invoke(Unknown Source:4)
    at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndspatched(Undispatched.kt:66)
    at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:43)
    at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:165)
    at kotlinx.coroutines.BuildersKt.withContext(Unknown Source:1)
    at androidx.work.impl.WorkerWrapper$launch$1.invokeSuspend(WorkerWrapper.kt:98)
    at androidx.work.impl.WorkerWrapper$launch$1.invoke(Unknown Source:8)
    at androidx.work.impl.WorkerWrapper$launch$1.invoke(Unknown Source:4)
    at androidx.work.ListenableFutureKt$launchFuture$1$2.invokeSuspend(ListenableFuture.kt:42)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
    at androidx.work.impl.utils.SerialExecutorImpl$Task.run(SerialExecutorImpl.java:96)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1156)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:651)
    at java.lang.Thread.run(Thread.java:1119)
Could not create Worker com.example.myani.data.notification.AnilistNotificationWorker

I tried methods where I didn't use Hilt and I tried to remove the sharedPreferences variable just to see if it was an issue with the Worker itself not Hilt and I saw that it works if I remove sharedPreferences parameter.

1 Answer 1

3

The main issue is that you use androidx.hilt:hilt-common instead of androidx.hilt:hilt-compiler. Replace

androidx-hilt-common = { group = "androidx.hilt", name = "hilt-common", version.ref = "hiltCommon" }

with

androidx-hilt-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hiltCommon" }

It also must be used with the annoation processor. It should work with kapt(libs.androidx.hilt.compiler), but for some reason it didn't. Since kapt is succeeded by KSP now, I didn't investigate further, because switching to KSP works like a charm:

ksp(libs.androidx.hilt.compiler)//Important dependencies

You also need to switch the other dependencies over to KSP, like this:

ksp(libs.hilt.android.compiler)//Important dependencies

Just set up KSP first as explained in the link above, and everything should work.


And while you're at it, you should move all versions to the version catalog. Especially the duplicated Hilt version you use for the plugin can easily be forgotten to be updated when you'll update Hilt sometime in the future. Also, the versions hiltCommon and hiltWork should be merged and more appropriately named androidxHilt.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.