【问题标题】:init is not called when injecting viewModel using Hilt使用 Hilt 注入 viewModel 时不调用 init
【发布时间】:2021-06-24 15:06:09
【问题描述】:

我想在 ViewModel 初始化时发出 API 请求。这就是为什么我在 init 方法中发出 API 请求;当我在 Activity 中注入 viewModel 时,期待init 被触发。我做错了什么?

MainViewModel.kt

@HiltViewModel
class MainViewModel @Inject constructor(private val mainRepository: MainRepo) : ViewModel() {
companion object {
    var TAG = "MainViewModel**"
}

init {
    Log.d(TAG, "NOT TRIGGERED: ")

    viewModelScope.launch {
        val album1: List<AlbumItem> = mainRepository.getAlbums()
    }
}}

MainActivity.kt

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private val mainViewModel : MainViewModel by viewModels() // injecting viewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding: ActivityMainBinding =
            DataBindingUtil.setContentView(this, R.layout.activity_main)
    }
}

【问题讨论】:

  • init会在调用主构造函数的时候被调用,这里是不是调用了?
  • @Jagar,我可以成功地将对象创建为MainRepo 类。它是在主构造函数中创建的。我认为,主构造函数中的一切都很好。但是有一种情况是,当我从 viewModel 内部的活动中调用一个函数时,首先会触发 init,然后调用该函数。正如我在问题中所说,我希望在 Activity 中注入 viewModel 时触发init

标签: android kotlin dependency-injection dagger dagger-hilt


【解决方案1】:

您对注入的委托有误解。

private val mainViewModel : MainViewModel by viewModels() // injecting viewModel (Wrong)

这不是匕首/刀柄注射。这是对 AndroidKTX 提供的惰性委托的调用。所以你得到的行为是预期的,当你第一次访问属性 mainViewModel 时,你的 ViewModel 将被创建(而不是注入)。所以你的 init {} 块的时间是预期的。

来自 Dagger/Hilt 的文档 (https://dagger.dev/hilt/view-model.html)

警告:即使视图模型有 @Inject 构造函数,直接从 Dagger 请求它(例如,通过字段注入)也是错误的,因为这会导致多个实例。必须通过 ViewModelProvider API 检索视图模型。这在编译时由 Hilt 进行检查。

您可以做的是在您的onCreate 方法中访问mainViewModel,这将尽早触发init 块。 或者删除委托并手动初始化onCreate中的mainViewModel

mainViewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)

【讨论】:

    猜你喜欢
    • 2021-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多