Jetpack组件的MVVM模式下,Dialog的处理

前言

最近在搞新项目,新项目使用Jetpack组件开发,其中就有涉及到了Dialog的问题如何和Jetpack的组件相结合的问题,这里记录一下。

初步按照需求的实现效果如下:

fc519e150d6a27173b43f042c9786c8e.gif

这里有几点需要说一下:

  • 实时监控是Activity,它下面包含3个Fragment子页面,但是他们有一个共同点,就是这个选择的站点是3个Fragment公用的,也就是说我在实时数据fragment选择了一个站点后,在实时一览界面也需要显示这个站点的数据。

  • 这里涉及到Fragment之间的通信,假如没有使用MVVM框架的话,这里很容易实现,也就是把选中的数据放到Activity中,Dialog的弹出也在Activity中实现,Activity和Fragment之间通过接口通信即可,但是这里使用MVVM架构就不必这么麻烦了。

  • 在我之前的文章里说过,Activity和Fragment之间的通信使用共享ViewModel来完成,文章地址# Fragment和Activity最佳通信方式 --- 共享ViewModel: ,当然这里也不是本章内容的重点。

上面基本说明白了需求和大概思路,但是这个Dialog问题我们还不好处理,主要有下面几个问题:

  • 我们知道弹出Dialog需要一个Context,按正常思路我们在点击上面例子中的实时一览Fragment的界面上的按钮,会调用共享ViewModel(这里是SiteTreeViewModel即站点树)中的函数来弹出dialog,这里从XML或者Fragment代码中需要传递Context给ViewModel,这就明显不符合MVVM的思想了,即VM层不能持有View层引用。

  • 按照思路,我们会在Activity中弹出Dialog,首先这个Dialog的数据即站点树是需要从后台加载的,我们就默认在Activity的ViewModel中去执行获取站点树的逻辑,然后选中后的结果我们也应该保存在共享ViewModel中,这里当然没问题,但是当Dialog比较复杂时,这里和Activity就有比较多的关联性,而且公用性不强,所以这里最好的办法是使用DialogFragment,把DialogFragment中的所有逻辑、数据都放在DialogFragment的ViewModel中,这样不仅能共享和实现需求,也有了生命周期,在使用ViewModel中的LiveData也更安全。

好了,带着上面问题,我们来仔细梳理一下。

正文

共享ViewModel

既然这里使用了DialogFragment,那上面的GIF图中的例子就是4个Fragment和1个Activity直接的数据共享,首先是站点树SiteTreeDialogFragment的三剑客:

image.png

那这里的SiteTreeViewModel就成了共享ViewModel,至于如何共享这个就不仔细介绍了,在Activity中获取通过扩展函数viewModels():

image.png

对于其他4个Fragment都不用说了,使用activityViewModels()即可

image.png

这样操作后,我们的共享ViewModel便完成了,在各自的Fragment里observe共享ViewModel中的数据即可:

image.png

在共享ViewModel中保存选中的结果:

image.png

弹出Dialog

我们知道MVVM架构的核心是数据驱动UI,所以我们在ViewModel拿到Context去弹出一个Dialog明显不合理,所以这里最简单的办法也就是在共享ViewModel中使用一个变量来保存是否弹出Dialog,然后这个由Activity来observe即可:

在共享ViewModel定义boolean类型的LiveData,表示是否弹出Dialog:

image.png

在点击Fragment中需要弹窗时把这个置为true即可:

image.png

最后在Activity中进行observe:

image.png

这样便可以做到数据驱动显示界面的思想了。

总结

其实本篇文章比较简单,主要就是2个核心思想,对于复杂逻辑的Dialog为了更好的利用Jetpack组件的好处可以改写为DialogFragment,还有就是数据驱动思想,在ViewModel中千万不能持有View层的引用。

猜你喜欢

转载自juejin.im/post/7035146520332599303
今日推荐