使用 Hilt 注入 viewModel 时不会调用 init

Yun*_*ade 8 android dependency-injection kotlin dagger dagger-hilt

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

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()
    }
}}
Run Code Online (Sandbox Code Playgroud)

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 18

您误解了注入委托。

private val mainViewModel : MainViewModel by viewModels() // injecting viewModel (Wrong)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

mainViewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
Run Code Online (Sandbox Code Playgroud)