【问题标题】:How can I use dependency injection in CoroutineWorker with hilt?如何在 CoroutineWorker 中使用带柄的依赖注入?
【发布时间】:2021-09-08 11:18:18
【问题描述】:

我正在学习依赖注入,以下代码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) {
           ...
        }
    }

    ..
}

添加内容

致安德鲁:谢谢!

在这个question中,你告诉我@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 {   
                ..
        }

【问题讨论】:

    标签: kotlin dependency-injection dagger-hilt


    【解决方案1】:

    你必须用@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 并删除默认初始化程序:

    应用程序代码

    @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 并告诉它如何创建一个 plantdao 实例。在下一步(代码 b)中,您通过构造函数注入它来保留您的 plantdao 实例。您必须首先提供它(通过模块),然后才能保留它(通过构造函数注入)。

    【讨论】:

    • 谢谢!请您看看我在问题中添加的内容吗?
    • 非常感谢!你的意思是我应该在我编辑的问题中使用代码 D 来使用构造函数进行依赖注入?
    • @HelloCW 是的。
    猜你喜欢
    • 2021-04-16
    • 1970-01-01
    • 2011-05-05
    • 2013-01-29
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多