为什么我不对片段使用SharedViewModel?

哈伯,你好!

组织片段之间的交互的任务非常普遍。乍一看,ShareViewModel对此非常有用。我们使用owner =我们的活动创建一个ViewModel,在其中显示我们的片段,并在每个片段中获取该ViewModel。因为如果ViewModel的所有者是活动,则片段将获得相同的ViewModel实例,这使它们可以交换数据,调用方法等。这是文档中的链接

下图显示了3个片段的交互方案。

图片

那些。我们要做的事情:在每个片段中,我们都获得了需要与之交互的那些片段的SharedViewModel。

我认为这不是最佳解决方案。因为:

  1. *VM. ViewModel View. ViewModel LiveData, View, .. ViewModel - , View.
  2. SharedViewModel — . , SharedViewModel , , . - .
  3. SharedViewModel, . , , .

仅当有几个完全相同的片段具有相同的数据时,才可以使用SharedViewModel。在我的实践中,没有这种情况。可能有两个相同的片段,但是每个片段的ViewModel状态不同,SharedViewModel对其无效。

SharedViewModel带来了很多问题。您开始感到困惑,所有东西都被依赖所淹没,代码很复杂。当Fragment + ViewModel是黑匣子时,工作起来要容易得多。

可以提供什么解决方案?

每个片段都以自己的方式与之交互的简单服务。

图片

该服务必须在每个ViewModel内部传递。借助DI和范围(Dagger,Koin和其他任何功能),可以轻松,轻松地完成此操作。如果服务应在活动的上下文中使用,请在此活动的范围内创建该服务,并将其传递给每个ViewModel。

看看发生了什么:我们从片段中删除了所有SharedViewModel。现在,每个片段对其他片段一无所知。如果我们想为该方案添加新的片段,则只需将viewModel D与我们的服务连接即可。如果片段应响应服务某些属性的更改-只需订阅它。我们不再需要了解其他人的ViewModel。并且此服务将比任何ViewModel都要简单得多,它将更易于理解该服务。

似乎在一个屏幕上没有那么多相互作用的片段。在电话上-也许。在平板电脑上-您不能再说了。FragmentContainerView有助于在任何布局中使用片段,如果应用程序具有许多具有生命周期的通用组件,这将非常方便。

奖励:如何创建片段?


像这样:SomeFragment()

那么参数呢?

随着ViewModel的出现,我不再使用参数。我不会通过捆绑包将任何内容传递给片段(Android Studio仍然提供了创建带有参数的片段并通过static方法创建片段的功能),我没有在导航组件中使用Safety NavArgs

所有这些使片段成为条件。例如,我们不能仅仅提取一个片段并将其添加到ViewPager中。必须考虑如何传递参数。或另一个示例:您创建了一个带参数的片段,在其中工作,数据已更改,该片段已经显示了其他内容。我们更改了设备配置(上交),使用过时的参数重新创建了片段,而ViewModel已经包含其他数据。并且开始参数等的实现。

我在ViewModel中删除了所有这些。我使用传递参数的相同服务。它的工作方式类似于Safety NavArgs。 ViewModel通过参数类的类型向服务请求参数。成功检索参数后,服务将其删除(工作方式如Push / Pop)。

这立即解决了更改配置的问题:再次创建了该片段,并且ViewModel已经包含当前数据,只需要将它们与View连接即可。

当参数通过bundle传递时,还有一个问题-这超出了允许的数量。如果传输的数据量超过500 kb,则该应用程序可能由于Binder.java中的异常而崩溃。这导致创建了不同的库,这些库通过SD传输参数,与使用RAM相比,速度不是很快。

通常,这些工具很酷,一切都很灵活,但是您需要小心。

就这样,谢谢收看!

All Articles