如何在带有刀柄的 CoroutineWorker 中使用依赖注入?
How can I use dependency injection in CoroutineWorker with hilt?
我正在学习依赖注入,以下代码A和代码B来自项目https://github.com/android/sunflower
作者在代码A中定义了一个依赖注入PlantDao
,但是在代码B中用代码database.plantDao()
手动创建了一个PlantDao
对象
为什么作者不对代码 B 中的对象 PlantDao
使用依赖注入?如何在代码 B 中对对象 PlantDao
使用依赖注入?
代码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()
}
...
}
代码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) {
...
}
}
..
}
添加内容
致安德鲁:谢谢!
在这个中,你告诉我@InstallIn(SingletonComponent::class)
将对整个应用程序可用,你可以看图1。
作者在代码A中定义了一个PlantDao
的依赖注入对象,安装为SingletonComponent::class
.
所以我认为PlantDao
的对象对整个应用程序都是可用的,为什么我不能直接在代码B中使用PlantDao的依赖注入对象呢?
图片 1
代码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 {
..
}
您必须使用 @HiltWorker
注释您的 worker,使用 @Assisted
注释您的上下文和参数,使用 @AssistedInject
注释您的构造函数,然后您可以构造函数注入您的 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) {
...
}
}
..
}
此外,您必须将默认的 WorkerFactory 更改为 hiltWorkerFactory 并删除默认的初始化程序:
AppCode
@HiltAndroidApp
class ExampleApplication : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
AndroidManifest.xml
<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'
请注意,稍后将 androidx.work 更新到 2.6 时,某些流程会发生变化。你可以阅读更多here
编辑
你可以直接在代码b中使用你的依赖注入plantdao。这就是构造函数中 private val database: AppDatabase
的含义。在第一步中,您将 plantdao 提供给 hilt 并告诉它如何创建 plantdao 的实例。在下一步(代码 b)中,您通过构造函数注入它来保留 plantdao 的实例。您必须首先将它提供给 hilt(通过模块),然后您可以保留它(通过构造函数注入)。
我正在学习依赖注入,以下代码A和代码B来自项目https://github.com/android/sunflower
作者在代码A中定义了一个依赖注入PlantDao
,但是在代码B中用代码database.plantDao()
手动创建了一个PlantDao
对象
为什么作者不对代码 B 中的对象 PlantDao
使用依赖注入?如何在代码 B 中对对象 PlantDao
使用依赖注入?
代码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()
}
...
}
代码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) {
...
}
}
..
}
添加内容
致安德鲁:谢谢!
在这个@InstallIn(SingletonComponent::class)
将对整个应用程序可用,你可以看图1。
作者在代码A中定义了一个PlantDao
的依赖注入对象,安装为SingletonComponent::class
.
所以我认为PlantDao
的对象对整个应用程序都是可用的,为什么我不能直接在代码B中使用PlantDao的依赖注入对象呢?
图片 1
代码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 {
..
}
您必须使用 @HiltWorker
注释您的 worker,使用 @Assisted
注释您的上下文和参数,使用 @AssistedInject
注释您的构造函数,然后您可以构造函数注入您的 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) {
...
}
}
..
}
此外,您必须将默认的 WorkerFactory 更改为 hiltWorkerFactory 并删除默认的初始化程序:
AppCode
@HiltAndroidApp
class ExampleApplication : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration() =
Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
}
AndroidManifest.xml
<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'
请注意,稍后将 androidx.work 更新到 2.6 时,某些流程会发生变化。你可以阅读更多here
编辑
你可以直接在代码b中使用你的依赖注入plantdao。这就是构造函数中 private val database: AppDatabase
的含义。在第一步中,您将 plantdao 提供给 hilt 并告诉它如何创建 plantdao 的实例。在下一步(代码 b)中,您通过构造函数注入它来保留 plantdao 的实例。您必须首先将它提供给 hilt(通过模块),然后您可以保留它(通过构造函数注入)。