【问题标题】:Is passing MutableLiveData to other ViewModels valid practice?将 MutableLiveData 传递给其他 ViewModel 是否有效?
【发布时间】:2020-08-07 07:40:51
【问题描述】:

我有一个场景,其中两个片段(A 和 B)需要共享一个对象列表,这些对象可以从两个屏幕上进行变异。 A 和 B 片段各有一个对应的 ViewModel(A_ViewModel 和 B_ViewModel)。它们包含一些关于如何改变共享数据的逻辑。

为了保持共享数据的完整性,我创建了 AB_Flow_ViewModel,它是活动范围的,包含包装在 MutableLiveData 中的共享数据。

我决定将 MutableLiveData 对象作为构造函数参数传递给 A 和 B 子片段。

我从未在任何地方看到过这种方法,但它似乎对我来说非常有效。

这样做有什么缺点吗?

这是我的解决方案的伪代码:

// Navigation: (A ->  B)
class A() : Fragment() {

  private val viewModel: A_ViewModel ...

  override fun onViewCreated(
      view: View,
      savedInstanceState: Bundle?
  ) {
    super.onViewCreated(view, savedInstanceState)
    viewModel.sharedData.observe {
      ...
    }
  }

}


class A_ViewModel @Inject  constructor(
    val sharedData: MutableLiveData<List<Any>>
) : ViewModel() {

  fun changeSharedData(newSharedData: List<Any>) {
    sharedData.value = newSharedData
  }
}

@Module
class A_Module {

  @Provides
  @FragmentScoped
  fun provideSharedData(fragment: A) =
      fragment.activityViewModels<AB_Flow_ViewModel>().value.sharedData
}

class B() : Fragment() {

  private val viewModel: A_ViewModel ...

  override fun onViewCreated(
      view: View,
      savedInstanceState: Bundle?
  ) {
    super.onViewCreated(view, savedInstanceState)
    viewModel.sharedData.observe {
      ...
    }
  }
}

@Module
class B_Module {

  @Provides
  @FragmentScoped
  fun provideSharedData(fragment: B) =
      fragment.activityViewModels<AB_Flow_ViewModel>().value.sharedData
}


class B_ViewModel @Inject constructor(
    val sharedData: MutableLiveData<List<Any>>
) : ViewModel() {
  fun changeSharedData(newSharedData: List<Any>) {
    sharedData.value = newSharedData
  }
}

class AB_Flow_ViewModel() : ViewModel() {
  val sharedData = MutableLiveData<List<Any>>()
}

【问题讨论】:

    标签: android mvvm viewmodel android-livedata


    【解决方案1】:

    我强烈建议不要在两个 Fragment 之间共享 MutableLiveData,如果您遇到错误,调试起来会非常困难,因为您不知道是谁在更改该数据以及在哪里导致这种奇怪的状态。 我喜欢做的是将我所有的 MutableLiveData 保存在 ViewModel 中,并且只将 LiveData 暴露给 Fragments/View 以进行观察。 MutableLiveData 需要发生的每一个变化我都通过 ViewModel 中的一个函数来完成。

    private val _sharedData = MutableLiveData<List<Any>>()
    val sharedData: LiveData<List<Any>>
        get() = _sharedData
    

    我会将有趣的 changeSharedData 放在 AB_Flow_ViewModel 中,并将所有逻辑放在一个 ViewModel 中,而不是两个。如果 FragA 和 FragB 的逻辑需要不同,我将使用两种不同的方法来更改相同的 LiveDdata

    【讨论】:

    • 感谢您的回答!我知道,这是 Google 提出的解决方案,但如果我这样做,代价是我的父 ViewModel 会变得很大,如果我按照描述的方式这样做,就可以避免这种情况。我同意你的观点,它可能更难调试。此外,MutableLiveData 仅向 A 和 B ViewModel 公开,而不向视图公开。
    • 您可以根据功能组织您的 ViewModel,它们不一定需要包含来自 FragA 和 FragB 的所有逻辑。如果它有帮助,请将此答案标记为已接受,以便它也可以帮助其他人。如果您还有其他问题,请与我联系,我很乐意为您提供帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 2012-12-26
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多