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

时间:2017-11-23 16:05:18

标签: android mvvm android-viewmodel

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

让我们说在我的应用程序中我有一个带有两个片段的活动(使用Viewpager)。这两个片段做了不同的事情(因此可能有自己的ViewModel?),但它们也需要各种类似的数据。

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

这看起来像这样:

enter image description here

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

enter image description here

这被暗示here例如,但这不是一个好习惯,因为relationship in MVVM通常是

  

查看n - 1 ViewModel n - 1模型

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

2 个答案:

答案 0 :(得分:9)

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

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

希望这能回答你的问题。

更新:我找到了a link to a sample fragment in Google samples。查看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();
}

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

答案 1 :(得分:0)

最新答案,但我问了自己同样的问题,并在Google指南中找到了答案。 特别是对于片段,它在Google文档中有明确规定:https://developer.android.com/topic/libraries/architecture/viewmodel#sharing

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

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

class MasterFragment : Fragment() {

    private lateinit var itemSelector: Selector

    private lateinit var model: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        model = activity?.run {
            ViewModelProviders.of(this)[SharedViewModel::class.java]
        } ?: throw Exception("Invalid Activity")
        itemSelector.setOnClickListener { item ->
        // Update the UI
        }
    }
}

class DetailFragment : Fragment() {

    private lateinit var model: SharedViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        model = activity?.run {
            ViewModelProviders.of(this)[SharedViewModel::class.java]
        } ?: throw Exception("Invalid Activity")
        model.selected.observe(this, Observer<Item> { item ->
            // Update the UI
        })
    }
}