【问题标题】:Why do I need ViewModelFactory in android?为什么我需要在 android 中使用 ViewModelFactory?
【发布时间】:2021-11-29 03:24:29
【问题描述】:

我正在尝试在 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()
            }
        })

    }
}

【问题讨论】:

    标签: android kotlin mvvm viewmodel android-viewmodel


    【解决方案1】:
    // Question 1: How can I pass constructor parameter if I use this delegate feature?
    // private lateint var viewModel: MainViewModel by viewModels()
    

    您会将ViewModelFactory 传递为a parameter to viewModels()。或者,根据参数的性质,使用依赖反转框架(Dagger/Hilt、Koin 等)。在您的情况下,您似乎正在传递某种存储库,在这种情况下,依赖反转框架是一种流行的解决方案。

       // Question 2: Why do I need this factory class / method as it works without these two lines.
    

    因为它实际上不起作用。特别是,MainViewModel 实例不会在配置更改(例如,屏幕旋转)后继续存在。如果你想正确使用 Jetpack ViewModel 系统,ViewModel 系统必须实例化你的MainViewModel

    【讨论】:

    • private lateint var viewModel: MainViewModel by viewModels() 如何在不使用 hilt 的情况下使用这种方法传递存储库?你能给我举个例子吗?
    • @CodeLover:“你能给我举个例子吗?” -- 我有很多使用 Koin 进行依赖倒置的例子。我没有使用by viewModels() 而不使用依赖倒置的示例。
    【解决方案2】:

    这是关于这个主题的另一个帖子Why a viewmodel factory is needed in Android?

    如果 ViewModelFactory 需要基本构造函数之外的其他参数,则使用 ViewModelFactory 创建。

    目的是关注点分离,您不应该在 Activity 中实例化 ViewModel,因为 Activity 必须知道 ViewModel 所需的所有参数。目标是让您的视图代码尽可能地笨拙,因此在您的 Activity 中保留对数据层代码和业务逻辑的引用不是一个好主意。例如:存储库

    此外,ViewModelProvider 允许您在需要时在活动和片段之间共享 ViewModel 的单个实例,这可以让您在多个位置维护状态而无需传递数据。

    这是一个关于 MVVM 的 android 开发课程,它包括一个关于如何正确使用 ViewModelFactory https://developer.android.com/codelabs/kotlin-android-training-view-model#7

    的课程

    【讨论】:

    • 第二句话有点误导。即使 ViewModel 有一个空的构造函数,也会使用 ViewModelFactory,尽管您可以使用默认的 ViewModelFactory,这样您就不必通过不传递工厂参数来创建自己的。
    • 是的,这是真的,根据我的经验,如果你有额外的参数,你只需要实现你自己的
    猜你喜欢
    • 1970-01-01
    • 2021-11-12
    • 2016-09-06
    • 1970-01-01
    • 2015-01-07
    • 1970-01-01
    • 2015-10-10
    • 1970-01-01
    • 2019-06-09
    相关资源
    最近更新 更多