Android MVVM:具有多个片段的活动 - 在何处放置共享的LiveData?

sta*_*uel 28 android mvvm android-viewmodel

我有一个关于android ViewModels的架构问题:

假设我的应用程序中有一个包含两个片段的Activity(使用Viewpager).这两个片段做了不同的事情(因此可能有自己的ViewModel?),但它们也需要各种类似的数据.

例如,如果网络连接可用或不存在(并且两个片段在没有连接的情况下显示不同的错误UI),或者某些用户设置来自服务器并且同等地影响两个片段,则这是状态.

这看起来像这样:

在此输入图像描述

现在我的问题是如何在使用ViewModels时处理这种情况?视图是否观察多个ViewModel是好的,就像我有一个ViewModel用于Activity(保持两个都需要的状态)和每个片段一个,如下所示:

在此输入图像描述

这在这里暗示,但这不是一个好的做法,因为MVVM中关系通常是

查看n - 1 ViewModel n - 1模型

但我不确定这种共享LiveData的正确位置在哪里?

小智 12

迟到的答案,但我问了自己同样的问题,并在 Google 指南中找到了答案。特别是对于片段,它在谷歌文档中明确提到here

class SharedViewModel : ViewModel() {
    val selected = MutableLiveData<Item>()

    fun select(item: Item) {
        selected.value = item
    }
}

class MasterFragment : Fragment() {

    private lateinit var itemSelector: Selector

    // Use the 'by activityViewModels()' Kotlin property delegate
    // from the fragment-ktx artifact
    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        itemSelector.setOnClickListener { item ->
            // Update the UI
        }
    }
}

class DetailFragment : Fragment() {

    // Use the 'by activityViewModels()' Kotlin property delegate
    // from the fragment-ktx artifact
    private val model: SharedViewModel by activityViewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        model.selected.observe(viewLifecycleOwner, Observer<Item> { item ->
            // Update the UI
        })
    }
}
Run Code Online (Sandbox Code Playgroud)


kar*_*sad 10

我认为ViewModel背后的概念是它应该与单个" 屏幕 "而不是" 视图 "相关.因此,按照该逻辑,我认为如果多个片段引用相同的ViewModel,则可以使用相同的ViewModel,因为它们在技术上属于相同的" 屏幕 ".

在片段中,您可以请求包含LiveData实例的ViewModel的活动,并根据需要为您提供更新.

希望这能回答你的问题.

更新:我在Google示例中找到了一个示例片段的链接.查看onCreateView()方法.粘贴下面的代码以供参考:

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    final View root = inflater.inflate(R.layout.addtask_frag, container, false);
    if (mViewDataBinding == null) {
        mViewDataBinding = AddtaskFragBinding.bind(root);
    }

    mViewModel = AddEditTaskActivity.obtainViewModel(getActivity());

    mViewDataBinding.setViewmodel(mViewModel);

    setHasOptionsMenu(true);
    setRetainInstance(false);

    return mViewDataBinding.getRoot();
}
Run Code Online (Sandbox Code Playgroud)

PS如果您找到了更好的解决方案/答案/练习,请知道.

  • 我认为这是一个更通用的问题 - 我可以在Activity和Fragment之间共享一个viewModel吗?如果他们有共同的代码或共同的"状态",似乎可以这样做.我粘贴的代码只是一个例子.因此,理论上,您可以使用Activity的ViewModel中的常用"状态"或代码来创建多个片段.这回答了你的评论吗? (3认同)