Android ViewModel @ViewModelInject 中的 Hilt Dagger 注入接口出现 UninitializedPropertyAccessException

Android Hilt dagger inject interface in viewModel @ViewModelInject got UninitializedPropertyAccessException

我正在试用 Hilt Codelab https://codelabs.developers.google.com/codelabs/android-hilt#10

它与 Activity 和 Fragment

一起工作正常

logger 是一个 RoomDB

然后我尝试用这个 article

将记录器注入 viewModel

通过添加

implementation "androidx.hilt:hilt-lifecycle-viewmodel
    :1.0.0-alpha02"
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'

视图模型代码

class RecordFragmentViewModel @ViewModelInject constructor(@Assisted private val savedStateHandle: SavedStateHandle) :
    ViewModel() {
    @DatabaseLogger
    @Inject
    lateinit var logger: LoggerDataSource

Class 要注入的记录器

 class LoggerLocalDataSource 
@Inject constructor(private val logDao: LogDao) : LoggerDataSource {

日志模块

@Qualifier
annotation class InMemoryLogger

@Qualifier
annotation class DatabaseLogger

@InstallIn(ApplicationComponent::class)
@Module
abstract class LoggingDatabaseModule {

    @DatabaseLogger
    @Singleton
    @Binds
    abstract fun bindDatabaseLogger(impl: LoggerLocalDataSource): LoggerDataSource
}

@InstallIn(ActivityComponent::class)
@Module
abstract class LoggingInMemoryModule {

    @InMemoryLogger
    @ActivityScoped
    @Binds
    abstract fun bindInMemoryLogger(impl: LoggerInMemoryDataSource): LoggerDataSource
}

数据库模块

@InstallIn(ApplicationComponent::class)
@Module
object DatabaseModule {

    @Provides
    @Singleton
    fun provideDatabase(@ApplicationContext appContext: Context): AppDatabase {
        return Room.databaseBuilder(
            appContext,
            AppDatabase::class.java,
            "logging.db"
        ).build()
    }

    @Provides
    fun provideLogDao(database: AppDatabase): LogDao {
        return database.logDao()
    }
}

编译成功,运行没有错误。 但是,我使用调试来观察记录器及其得到的。

Method threw 'kotlin.UninitializedPropertyAccessException' exception.

我在 运行 抛出 logger.something() 时调用

Fatal Exception: kotlin.UninitializedPropertyAccessException
lateinit property logger has not been initialized

更多信息 https://dagger.dev/hilt/migration-guide.html

https://codelabs.developers.google.com/codelabs/android-hilt#10

https://medium.com/mobile-app-development-publication/injecting-viewmodel-with-dagger-hilt-54ca2e433865

由于 LoggerDataSource 是一个接口,我们需要指定我们需要注入哪个实现。感谢@Andrew 提出注入构造函数的想法

class RecordFragmentViewModel
@ViewModelInject
constructor(@Assisted private val savedStateHandle: SavedStateHandle,
            @DatabaseLogger private val logger: LoggerDataSource) :
    ViewModel(), LifecycleObserver {

指定

@Qualifier
annotation class InMemoryLogger

@Qualifier
annotation class DatabaseLogger

@InstallIn(ApplicationComponent::class)
@Module
abstract class LoggingDatabaseModule {

    @DatabaseLogger
    @Singleton
    @Binds
    abstract fun bindDatabaseLogger(impl: LoggerLocalDataSource): LoggerDataSource
}

@InstallIn(ActivityComponent::class)
@Module
abstract class LoggingInMemoryModule {

    @InMemoryLogger
    @ActivityScoped
    @Binds
    abstract fun bindInMemoryLogger(impl: LoggerInMemoryDataSource): LoggerDataSource
}