Reputation: 2255
I'm learning dependency injection, the following Code A and Code B are from the project https://github.com/android/sunflower
The author has defined a dependency injection PlantDao
in Code A, but a PlantDao
object is created with code database.plantDao()
manually in Code B.
Why doesn't the author use dependency injection with the object PlantDao
in Code B? How can I use dependency injection with the object PlantDao
in Code B?
Code A
@InstallIn(SingletonComponent::class)
@Module
class DatabaseModule {
@Singleton
@Provides
fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase {
return AppDatabase.getInstance(context)
}
@Provides
fun providePlantDao(appDatabase: AppDatabase): PlantDao {
return appDatabase.plantDao()
}
...
}
Code B
class SeedDatabaseWorker(
context: Context,
workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
try {
val filename = inputData.getString(KEY_FILENAME)
if (filename != null) {
applicationContext.assets.open(filename).use { inputStream ->
JsonReader(inputStream.reader()).use { jsonReader ->
...
val database = AppDatabase.getInstance(applicationContext)
database.plantDao().insertAll(plantList)
...
} else {
...
}
} catch (ex: Exception) {
...
}
}
..
}
Added Content
To Andrew: Thanks!
In this question, you told me that @InstallIn(SingletonComponent::class)
will be available to the entire application, you can see Image 1.
The author has defined a dependency injection object of PlantDao
in Code A and install it as SingletonComponent::class
.
So I think that the object of PlantDao
will be available to the entire application,why can't I use the dependency injection object of PlantDao directly in Code B?
Code D
class SeedDatabaseWorker @Inject constructor(
database: AppDatabase,
context: Context,
workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
try {
val filename = inputData.getString(KEY_FILENAME)
if (filename != null) {
applicationContext.assets.open(filename).use { inputStream ->
JsonReader(inputStream.reader()).use { jsonReader ->
...
database.plantDao().insertAll(plantList)
...
} else {
..
}
Upvotes: 0
Views: 2072
Reputation: 4712
You have to annotate your worker with @HiltWorker
, your context and params with @Assisted
, your constructor with @AssistedInject
and then you can constructor inject your dao.
@HiltWorker
class SeedDatabaseWorker @AssistedInject constructor(
@Assisted context: Context,
@Assisted workerParams: WorkerParameters,
private val database: AppDatabase
) : CoroutineWorker(context, workerParams) {
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
try {
val filename = inputData.getString(KEY_FILENAME)
if (filename != null) {
applicationContext.assets.open(filename).use { inputStream ->
JsonReader(inputStream.reader()).use { jsonReader ->
...
database.plantDao().insertAll(plantList)
...
} else {
...
}
} catch (ex: Exception) {
...
}
}
..
}
Furthermore, you have to change the default WorkerFactory to a hiltWorkerFactory and remove the default initializer:
@HiltAndroidApp
class ExampleApplication : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
tools:node="remove" />
implementation 'androidx.hilt:hilt-work:1.0.0'
kapt 'androidx.hilt:hilt-compiler:1.0.0'
implementation 'androidx.work:work-runtime-ktx:2.5.0'
Be aware that some processes change when later updating androidx.work to 2.6. You can read more here
You can use your dependency injection plantdao directly in code b. That's what private val database: AppDatabase
inside your constructor means. In the first step, you provided your plantdao to hilt and told it how to create an instance of plantdao. In the next step (code b), you retain an instance of your plantdao via constructor injecting it. You have to first provide it to hilt (via a module) and then you can retain it (via constructor injection).
Upvotes: 6