【问题标题】:Android ViewModel reference FragmentAndroid ViewModel 参考 Fragment
【发布时间】:2019-11-18 19:11:40
【问题描述】:

我是一名初学者 android 开发人员,正在寻找编写一个完整的喷气背包应用程序。我想知道从 ViewModel 与片段通信的最佳方式是说、显示对话框或导航到另一个片段。

我有这样的事情:

class Foo: ViewModel() {

    interface Callbacks {
        fun doSomethingWithUI()
        fun showBaz()
    }

    var callbacks: Callbacks? = null
}

然后在片段 onCreate 中,它会将自己设置为 viewmodels 回调对象。

查看文档,它指出 ViewModel 不应该持有任何相关的视图或生命周期,或者具有对活动的引用。考虑到这一点,ViewModel 正在引用具有活动的片段。

我想知道,为什么这很糟糕。一切似乎都正常工作,如果只有一个活动开始,我们会泄漏什么?为什么谷歌很清楚不要抓住这些东西,但从来没有真正说为什么不这样做。

另外,由于我做的不好,让 ViewModel 告诉片段说“显示带有此错误的对话框”的“正确”方式是什么

【问题讨论】:

    标签: android android-fragments kotlin android-lifecycle android-jetpack


    【解决方案1】:

    您可以将 Livedata 与 Observer 一起使用。例如,您可以使用 a
    Mutablelivedata<Boolean> 并将 Observer 附加到它。 您在 Fragment 中获取 Viewmodel,并将观察者附加到 Mutablelivedata<Boolean>,当 Mutablelivedata<Boolean> 更改为 true 时,它会显示一个对话框。当您第一次将 Observer 附加到 Livedata 并且数据发生更改时,将调用 Observer。

    【讨论】:

      【解决方案2】:

      这是一个非常广泛的主题,您绝对应该从谷歌查看架构示例,但简而言之就是这个想法。假设您希望有一些通知渠道来报告各种错误。那么:

      1. 在你的视图模型下,你可以定义private val errorsLiveData: MutableLiveData<Exception> = MutableLiveData()
      2. 在您的片段下,您可以像这样订阅流:
              myViewModel.getErrorsLiveData().observe(viewLifecycleOwner, Observer {
                  showError(it)
              })
      
      1. 视图模型如何报告错误:getErrorsLiveData().value = MyException(it)

      【讨论】:

        【解决方案3】:

        您可以先将实时数据创建为 Mutable 和 Immutable 两部分。可变的实时数据将仅在 viewModel 内部使用,而不可变的数据可以从片段或活动中观察到。

        class CarViewModel: ViewModel() {
        
        private val repo: EngineRepo() // an instance of your repository inside ViewModel
        private val _engine = MutableLiveData<List<Engines>>() //mutable live data to be used inside the viewModel
        val : LiveData<List<Engines>> = _engine //this is the observable live data
        

        现在,

        fun fetchEngineDetails() {
        viewModelScope.launch(Dispatchers.IO){
        
        _engine.postValue(repo.getEngine()) // calling the function inside your repo
        
          }
        }
        

        现在你已经完成了你的 viewModel 因此,要在片段中调用此 ViewModel,假设您可以创建 ViewModel 类的实例。

        class CarFragment: Fragment(){
        private val carViewModel: CarViewModel by viewModels()
        

        现在在您的 onCreate 方法中,您可以像这样使用 ViewModel 调用该函数:

        varViewModel.fetchEngineDetails()
        

        在 onCreateView 中,您可以像这样观察 livedata:

        carViewModel.engine.observe {(viewlifeCycleOwner)} {
        Toast.makeText(requireContext, "Number of engines is {it.size}, Toast.LENGTH_SHORT).show()  
        }
        

        请注意,要按照我在此处编写的方式在片段中使用或创建 ViewModel 类的实例,您必须在您的 gradles 中放置一些依赖项

        所以在你 build.gradle(项目)

        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5"
        

        在你的 build.gradle(App Module) 中

        内部插件添加:

        id 'androidx.navigation.safeargs.kotlin'
        

        内部依赖添加:

        implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
        implementation 'androidx.legacy:legacy-support-v4:1.0.0'
        implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
        implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
        implementation "android.arch.lifecycle:extensions:1.1.1"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-05-07
          • 1970-01-01
          • 2020-11-18
          • 2021-02-23
          • 1970-01-01
          • 2020-11-16
          • 2018-09-30
          • 1970-01-01
          相关资源
          最近更新 更多