ViewModel for Fragment而不是访问Activity ViewModel?

时间:2017-09-17 20:51:14

标签: android android-fragments mvvm kotlin android-architecture-components

问题非常简单。问题在于使用ViewModels,LiveData和其他相关的Lifecycle感知的arch方法。 我在NavDrawer中有一个Activity,可以在里面切换片段。
我还有一个案例,当屏幕上同时出现两个碎片时 - 这将是主要的痛苦。 One Fragment有一个嵌套Fragments的ViewPager(不要问为什么)。 另一个片段只是在用户执行某些操作时从第一个获取信息。这只是通过共享活动视图模型来实现的。但是应用程序本身有很多业务逻辑,随着视图模型越来越大,视图模型越来越大。
我想问的是 - 不是收据或规则如何解决这个问题,或者可能是如何通过修复整个项目结构来解决这个问题。我想问一下建议如何将android.arch.lifecycle样式中的MVVM方法应用于我的用例。 我只是在片段之间共享Activity ViewModel,但我还没有看到更复杂的东西。但很常见,这不是治愈方法。 enter image description here

你在这里可以看到什么 - 实际上是一团糟。关键是所有人都在分享ActivityViewModel。来自FirstFragment的连接(聚合)意味着ViewPager内的FirstFragment正在发起ChildFragments,并且他们也在使用相同的ActivityViewModel(杀了我)。因此,每个人都在使用一个共享的ViewModel。
我的建议是为每个Layer添加一个ViewModel。因此,Activity / Fragments / ChildFragments拥有自己的ViewModels。 但是这里出现了什么 - 我们应该如何沟通
可能的解决方案:

  • 每个组件有两个ViewModel。一个ViewModel将处理/委托业务逻辑,另一个将进行通信。 每个组件有两个视图模型 - 不太好,是吗?
  • 有旧的界面(请不!
  • 其他解决方法 - 比如DB / SharedPrefs / Realm更改了侦听器和事件总线(我太老了:()。

  • 您的解决方案在这里!

我说上述所有内容都违反了许多设计原则,那么我该怎么办? 我该怎么走出这个烂摊子?这里有Uncle Bob或其他superhero可以提供帮助吗?

P.S。 - 好吧,创建UML或其他图表并不是我的强项。对不起。
P.P.S。 - 我了解google samples

4 个答案:

答案 0 :(得分:3)

首先,对于 查看 多个 ViewModel没有任何害处。

我会考虑我的 ViewModel ,就像什么样的数据正在进行操作,并以某种方式对它们进行分组,这看起来很自然。

对于你的情况,如果片段和活动的逻辑非常相似,我认为你可以使用单ViewModel,但我会避免这种情况。

我要做的是将活动的ViewModel分解为更小的部分,并在ViewModel中重复使用正确的Fragments,这样我就不会有上帝ViewModel ,在 ViewModel 中的代码大致相同。

答案 1 :(得分:0)

我会建议,您可以针对整个用例处理两个ViewModel

制作一个ViewModel

让我们说 MyActivityViewModel 来处理与活动级别相关的所有逻辑。因此,如果任何片段逻辑与您的活动直接相关,则按如下所示共享您的ViewModel

ViewModelProviders.of(getActivity()).get(MyActivityViewModel.class); // Like this in fragment.

ViewModelProviders.of(this).get(MyActivityViewModel.class); // Like this in activity.

这将在您的活动片段 之间共享ViewModel


如果您必须在ViewModel之间共享逻辑,则另外一个FirstFragment将适用于ChildFragment

在这里您可以共享ViewModel,比方说FragmentViewModel,如下所示:

ViewModelProviders.of(this).get(FragmentViewModel.class); // Like this in FirstFragment which is having view pager.

ViewModelProviders.of(getParentFragment()).get(FragmentViewModel.class); // Like this in View pager fragments, getParentFragment() is First fragment in our case.

尽管如此,我们仍然可以在FirstFragment的子片段中使用活动级别 MyActivityViewModel ,例如:

ViewModelProviders.of(getActivity()).get(MyActivityViewModel.class);

答案 2 :(得分:0)

要解决FirstFragment与子片段共享视图模型的问题,可以使用以下代码从任何子片段访问FirstFragmentViewModel

    // in ChildFragment1
    val firstFragmentViewModel: FirstFragmentViewModel by viewModels(
        { requireParentFragment() }
    )

答案 3 :(得分:0)

这是Jeel Vankhede给出的答案的更新版本。和Kotlin的实现相同。

由于不推荐使用ViewModelProviders,我们现在必须使用ViewModelProvider。

以下是您在“活动”中的操作方式:

categories

这是您在Fragment中的操作方式:

id