Reputation: 11124
I trying on Hilt codelab https://codelabs.developers.google.com/codelabs/android-hilt#10
It's working fine with Activity and Fragment
logger is a RoomDB
Then I try to inject logger into viewModel with this article
By add
implementation "androidx.hilt:hilt-lifecycle-viewmodel
:1.0.0-alpha02"
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha02'
ViewModelCode
class RecordFragmentViewModel @ViewModelInject constructor(@Assisted private val savedStateHandle: SavedStateHandle) :
ViewModel() {
@DatabaseLogger
@Inject
lateinit var logger: LoggerDataSource
Class logger to inject
class LoggerLocalDataSource
@Inject constructor(private val logDao: LogDao) : LoggerDataSource {
LoggingModule
@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
}
DatabaseModule
@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()
}
}
It's compile and run without error. However, I use debug to watch logger and its got.
Method threw 'kotlin.UninitializedPropertyAccessException' exception.
I call logger.something() at run time its throw
Fatal Exception: kotlin.UninitializedPropertyAccessException
lateinit property logger has not been initialized
More info https://dagger.dev/hilt/migration-guide.html
https://codelabs.developers.google.com/codelabs/android-hilt#10
Upvotes: 6
Views: 9540
Reputation: 11124
Since LoggerDataSource is a interface we need to specify which implementation we need to inject. Thanks to @Andrew for the idea of inject to constructor
class RecordFragmentViewModel
@ViewModelInject
constructor(@Assisted private val savedStateHandle: SavedStateHandle,
@DatabaseLogger private val logger: LoggerDataSource) :
ViewModel(), LifecycleObserver {
To specify
@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
}
Upvotes: 4