我试图在ViewModel类中传递构造函数参数。但我不知道最好的方法是什么。请看看代码和注释,让我知道最简单和合适的方法。
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
// Question 1: How can I pass constructor parameter if I use this delegate feature?
// private lateint var viewModel: MainViewModel by viewModels()
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val repository = Repository()
// Passing constructor directly works.
viewModel = MainViewModel(repository)
// Question 2: Why do I need this factory class / method as it works without these two lines.
// val viewModelFactory = MainViewModelFactory(repository)
// viewModel = ViewModelProvider(this, viewModelFactory).get(MainViewModel::class.java)
viewModel.getPost()
viewModel.mResponse.observe(this, Observer { response ->
if (response.isSuccessful) {
Log.d("Response: ", response.body()?.userId.toString())
Log.d("Response: ", response.body()?.id.toString())
binding.textView.text = response.body()?.title.toString()
Log.d("Response: ", response.body()?.body.toString())
} else {
Log.d("Response: ", response.errorBody().toString())
binding.textView.text = response.code().toString()
}
})
}
}
// Question 1: How can I pass constructor parameter if I use this delegate feature?
// private lateint var viewModel: MainViewModel by viewModels()
将ViewModelFactory
作为参数传递给viewModels()
。或者,根据参数的性质,使用依赖反转框架(Dagger/Hilt, Koin等)。在您的情况下,您似乎正在传递某种存储库,在这种情况下,依赖倒置框架是一个流行的解决方案。
// Question 2: Why do I need this factory class / method as it works without these two lines.
因为它实际上不起作用。特别是,MainViewModel
实例不能在配置更改后存活(例如,屏幕旋转)。如果你想正确使用JetpackViewModel
系统,ViewModel
系统必须实例化你的MainViewModel
。
这是关于这个主题的另一个线程为什么在Android中需要一个视图模型工厂?
如果ViewModelFactory需要基本构造函数之外的额外参数,则使用ViewModelFactory来创建ViewModel。
目的是分离关注点,你不应该在Activity中实例化ViewModel,因为Activity必须知道ViewModel需要的所有参数。我们的目标是让视图代码尽可能的简洁,所以在Activity中保持对数据层代码和业务逻辑的引用并不是一个好主意。例:库
另外,如果你想的话,ViewModelProvider允许你在Activities和Fragments之间共享ViewModel的单个实例,这可以让你在多个地方维护状态而不需要传递数据。
这是一个关于MVVM的android开发课程,它包括一个关于如何正确使用ViewModelFactory https://developer.android.com/codelabs/kotlin-android-training-view-model#7