【问题标题】:Application dependency to ViewModel with HILT使用 HILT 对 ViewModel 的应用程序依赖
【发布时间】:2020-08-24 17:31:15
【问题描述】:

我想知道如何使用 Hilt 将应用程序依赖项传递给 ViewModel? 我正在尝试使用 AndroidViewModel,但我做不到。有人能帮我吗?一些简短的样本对我来说意义重大。

这是我的视图模型:

class MainViewModel @ViewModelInject constructor(
    private val application: Application,
    private val repository: Repository,
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {

这是我的刀柄模块

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

    @Singleton
    @Provides
    fun provideDatabase(
        @ApplicationContext context: Context
    ) = Room.databaseBuilder(
        context,
        MyDatabase::class.java,
        "my_database"
    ).build()

    @Singleton
    @Provides
    fun provideDao(database: MyDatabase) = database.myDao()

    @Singleton
    @Provides
    fun provideRepository(myDao: MyDao) = Repository(myDao)

    @Singleton
    @Provides
    fun provideApplicationContext() = MyApplication()

}

其他一切都很好,我收到了错误消息:

原因:java.lang.RuntimeException:无法创建实例 com.example.example.viewmodel.MainViewModel 类 引起:java.lang.InstantiationException: java.lang.Class 有 没有零参数的构造函数

【问题讨论】:

  • StefanJo,您有没有使用 hilt 在 AndroidViewModel 中传递应用程序实例的解决方案?

标签: android kotlin dagger-hilt


【解决方案1】:

你可以看到完整的源码https://github.com/Kotlin-Android-Open-Source/MVI-Coroutines-Flow/tree/dagger_hilt

  • 存储库:
@Singleton
class UserRepositoryImpl @Inject constructor(
    private val userApiService: UserApiService,
    private val dispatchers: CoroutineDispatchers,
    ...
) : UserRepository { ... }
  • 用例:

class AddUserUseCase @Inject constructor(private val userRepository: UserRepository) {
  suspend operator fun invoke(user: User) = userRepository.add(user)
}

class RemoveUserUseCase @Inject constructor(private val userRepository: UserRepository) {
  suspend operator fun invoke(user: User) = userRepository.remove(user)
}

class RefreshGetUsersUseCase @Inject constructor(private val userRepository: UserRepository) {
  suspend operator fun invoke() = userRepository.refresh()
}

...
  • ViewModel:
class MainVM @ViewModelInject constructor(
    private val getUsersUseCase: GetUsersUseCase,
    private val refreshGetUsers: RefreshGetUsersUseCase,
    private val removeUser: RemoveUserUseCase,
) : ViewModel() { ... }
  • 活动:

@AndroidEntryPoint
class MainActivity : AppCompatActivity(), View {
  private val mainVM by viewModels<MainVM>()
  
  ...
}

编辑:

注入应用上下文:

首先,去掉这个定义,因为Hilt已经提供了应用上下文:

    @Singleton
    @Provides
    fun provideApplicationContext() = MyApplication()

第二,在你的上下文参数上使用@ApplicationContext注解。

class MainViewModel @ViewModelInject constructor(
    @ApplicationContext private val context: Context,
    private val repository: Repository,
    @Assisted private val savedStateHandle: SavedStateHandle
) : ViewModel() {

【讨论】:

  • 但是您没有应用程序传入参数..
  • 更新答案,希望对你有所帮助
  • 这显示警告This field leaks a context object
【解决方案2】:

在构造函数中使用@ApplicationContext Context context作为参数。

【讨论】:

    猜你喜欢
    • 2021-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-18
    • 2011-09-25
    • 1970-01-01
    • 2012-06-15
    相关资源
    最近更新 更多