Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to inject WorkManager? #419

Open
Monabr opened this issue Jul 27, 2024 · 4 comments
Open

How to inject WorkManager? #419

Monabr opened this issue Jul 27, 2024 · 4 comments

Comments

@Monabr
Copy link

Monabr commented Jul 27, 2024

Hello.

I can't find how to inject WorkManager after searching the documentation.

Could you please tell me how to do this and update the documentation?

@evant
Copy link
Owner

evant commented Jul 27, 2024

You'll want to use a https://developer.android.com/reference/androidx/work/WorkerFactory to return your injected instances. Same pattern as what's suggested for fragments in the doc.

@Monabr
Copy link
Author

Monabr commented Jul 27, 2024

@evant Could you please provide a more detailed explanation of how to do this using the kotlin-inject library? Unfortunately, I couldn't figure it out no matter how hard I tried.

@AdriaBosch
Copy link

Hi, I just migrated an Android project from Hilt to kotlin-inject. This is a summary of the code I used to inject WorkManager

@Inject
class MyWorker(
    @Assisted
    private val appContext: Context,
    @Assisted
    private val params: WorkerParameters,
    // Other dependencies
) : CoroutineWorker(appContext, params) {
	
	override suspend fun doWork() {}
}


interface WorkManagerComponent {

    @Provides
    @IntoMap
    fun provideMyWorkerEntry(
        workerCreator: (context: Context, params: WorkerParameters) -> MyWorker,
    ): Pair<KClass<out ListenableWorker>, (Context, WorkerParameters) -> MyWorker> {
        return Pair(MyWorker::class, workerCreator)
    }

   // other workers

    val MyWorkerFactory.provide: WorkerFactory
        @Provides get() = this

    @Singleton
    @Provides
    fun provideWorkManager(context: Context): WorkManager {
        return WorkManager.getInstance(context)
    }
}


@Inject
class MyWorkerFactory(
    private val workersMap: Map<KClass<out ListenableWorker>, (Context, WorkerParameters) -> ListenableWorker>
) : WorkerFactory() {

	override fun createWorker(
	    appContext: Context,
	    workerClassName: String,
	    workerParameters: WorkerParameters
	): ListenableWorker? {
            val entry = workersMap.entries.find {
                Class.forName(workerClassName).isAssignableFrom(it.key.java)
            }
            val workerCreator = entry?.value ?: return null
            return workerCreator(appContext, workerParameters)
	}
}

Then provide WorkerFactory to your application class:

class MyApplication : Application(), Configuration.Provider {

	private lateinit var workerFactory: WorkerFactory

	override fun onCreate() {
		super.onCreate()

		// create your application component

		workerFactory = appComponent.workerFactory
	}

	override fun getWorkManagerConfiguration(): Configuration {
		return Configuration.Builder()
			.setWorkerFactory(workerFactory)
			.build()
	}
}

And don't forget to disable WorkManager initialization from your Manifest.

I hope it helps.

@julius-b
Copy link

Thank you so much @AdriaBosch, just a little note though. For me it wouldn't compile until I changed

    @Provides
    @IntoMap
    fun provideMyWorkerEntry(
        workerCreator: (context: Context, params: WorkerParameters) -> MyWorker,
    ): Pair<KClass<out ListenableWorker>, (Context, WorkerParameters) -> MyWorker> {
        return Pair(MyWorker::class, workerCreator)
    }

into

    @Provides
    @IntoMap
    fun provideMyWorkerEntry(
        workerCreator: (context: Context, params: WorkerParameters) -> MyWorker,
    ): Pair<KClass<out ListenableWorker>, (Context, WorkerParameters) -> **ListenableWorker**> {
        return Pair(MyWorker::class, workerCreator)
    }

Even though MyWorker implements ListenableWorker, I had to be the exact same for me to prevent this exception:

[ksp] Cannot find an @Inject constructor or provider for: Map<kotlin.reflect.KClass<out androidx.work.ListenableWorker>, kotlin.Function2<android.content.Context, androidx.work.WorkerParameters, androidx.work.ListenableWorker>>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants