How to use WorkManager with Hilt in Android
In the fast-paced world of mobile app development, managing background tasks effectively is a crucial aspect of creating robust and responsive applications. Whether it’s periodic data synchronization, notifications, or resource-intensive operations, Android developers often find themselves grappling with the complexities of background task execution. This is where WorkManager, a powerful and flexible library provided by Android, comes to the rescue.
In this article, we will embark on a journey to learn how to seamlessly integrate WorkManager with Hilt, a popular dependency injection framework.
Adding the dependencies
First, we need to add some dependencies to our project:
// Hilt
implementation 'androidx.hilt:hilt-work:1.0.0'
kapt 'androidx.hilt:hilt-compiler:1.0.0'
// WorkManager
implementation "androidx.work:work-runtime-ktx:2.8.1"
You can find more about the versions of the libraries in the official documents:
Note: If you haven’t already set up Dagger Hilt in your project, you can follow the official documentation to get it up and running seamlessly.
Code
A simple worker class would look like this:
class SimpleWorker(
appContext : Context,
params : WorkerParameters
) : Worker(appContext,params) {
override fun doWork(): Result {
// Do your background work
// Return result
return Result.success()
}
}
Consider a scenario where your background task requires access to various helper classes, data sources, or services. Without proper dependency management, you might find yourself tangled in a web of manual dependency instantiation and potential memory leaks.
To prevent that from happening, we use hilt to inject the required dependencies into our worker.
Let’s take for an example that our worker needs to access some functions in our repository class, and the latter is provided by Hilt and we need to inject it in the worker.
To inject our repository in the worker class, we have to use @HiltWorker
annotation in the class and annotate the constructor with @AssistedInject
The worker class would look like this:
@HiltWorker
class SimpleWorker @AssistedInject constructor(
private val repo : DefaultRepo,
@Assisted appContext : Context,
@Assisted params : WorkerParameters
) : Worker(appContext,params){
override fun doWork(): Result {
// Do your background work
// Return result
return Result.success()
}
}
You may notice that we annotated appContext and params with @Assisted
and for any other params we don’t have to.
The next step is to implement the Configuration.Provider
in the Application
class and provide a worker configuration as shown below:
@HiltAndroidApp
class AppClass : Application(), Configuration.Provider{
@Inject lateinit var workerFactory : HiltWorkerFactory
override fun getWorkManagerConfiguration(): Configuration {
return Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
}
Now if we run the application and start the WorkManager we will probably get a NoSuchMethodException
and that is because the application is still using the default WorkerFactory to initialize our worker, and the latter doesn’t know how to get an instance of the repository.
To solve this issue, we must remove the default initializer and we do that by adding this block to the AndroidManifest.xml
file:
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />
Everything should work perfectly now, to check a real world example of using WorkManager with Hilt, you can check the code of my app ViDown