Android MVVM UI 控件
Posted
技术标签:
【中文标题】Android MVVM UI 控件【英文标题】:Android MVVM UI control 【发布时间】:2020-11-26 11:35:11 【问题描述】:我开始在 android 上使用 LiveData 学习 MVVM。我认为显示和更新基本数据对我来说很清楚。我很难找到最佳实践的主题是控制 UI。
假设我有一个基本的用户界面,例如一个表单。它有几个 EditTextViews 来输入数据。最后它还有一个开关。如果它是ON,则会显示更多的 EditTextViews 来填充。当它OFF时,它们当然消失了。
我的问题是在哪里实现这个逻辑?
在活动/片段代码中?然后业务逻辑将涉及到 MVVM 的 VIEW 部分(我觉得不太好)。
在视图模型中?然后业务逻辑将存在于一个,比如说,数据缓存中。这样我就必须在 ViewModel 中创建一堆 boolean
getter 来计算单独视图可见性的值。然后在我的 Activity 中的 LiveData 更改订阅块中,我需要读取所有这些值并一一设置视图的可见性。
在单独的 Service/Helper/Util 类中?这与 #2 的解决方案相同,只是从 ViewModel 中提取的逻辑。
这里的最佳做法是什么?不过,同样的问题可以提出用户输入验证的主题(我猜这些领域有很多)。
【问题讨论】:
开/关状态是否会影响 UI 可见性以外的其他内容?如果没有 UI,它在业务逻辑中的作用是什么? 当它打开时,业务逻辑分别填充 POJO 中的字段,当它关闭时,相同的字段将被留空/清除。例如,如果Under Age开关打开,用户必须输入法定代表人的数据(母亲姓名等),这些数据需要保存。 按照我的理解,它是由 UI(用户单击按钮)驱动的,而不是从其他 POJO 属性派生的,例如出生日期VS现在?如果用户打开按钮,填写字段并将其关闭,POJO 应该有空值,无论 UI 中的字段不是空的,对吗? 正确。是的,我现在知道这个例子不是最好的。如您所述,在大多数用例中,必须从出生日期和当前日期计算未成年人。这只是一个场景的快速示例,有时需要显示一些 UI 组件,有时需要消失。 【参考方案1】:我会采用第二种方法,但实施方式略有不同(使用 DataBinding),灵感来自 Google 的示例 Sunflower 应用程序: https://github.com/android/sunflower 它应该引入 Jetpack 最佳实践,包括 MVVM。
然后,在我的 Activity 中的 LiveData 更改订阅块中,我需要读取所有这些值并一一设置视图的可见性。
您可以将布局订阅到视图模型(使用 DataBinding),而不是这样做,类似于:https://github.com/android/sunflower/blob/master/app/src/main/res/layout/fragment_plant_detail.xml
<data>
<import type="com.google.samples.apps.sunflower.data.Plant"/>
<variable
name="viewModel"
type="com.google.samples.apps.sunflower.viewmodels.PlantDetailViewModel" />
</data>
然后在布局本身中使用基于对视图模型的引用设置可见性,而无需获取器
app:isGone="@!viewModel.isUnderAge"
或
android:visibility="@viewModel.isUnderAge? View.VISIBLE : View.INVISIBLE"
【讨论】:
老实说,如果可能的话,我会避免使用 DataBinding。我有两个原因: - 就像我在原始问题的#1 选项中所说的那样,这会将业务逻辑放入应用程序的 VIEW 层。 - 当您将代码写入string
并让后台架构将其作为代码执行时,我通常不热衷于解决方案。如果一切看起来都正常(没有错别字、编译问题等),那么正确的功能就会发生。我会尽量避免,这真的不符合我对源代码的品味。
阅读这篇文章,了解为什么它很危险:medium.com/@hellotimmutton/…
我以前读过它,虽然我同意关注点分离的重要性,但我不同意他的解释。该模型应该与附加到它的任何 UI 一起使用,例如android:visibility=”@viewModel.showTitle ? View.VISIBLE : View.GONE”
是一个不好的例子——它描述的是 UI 状态,而不是业务逻辑状态。如果在业务逻辑中存在您不希望显示标题的状态,则添加反映该状态的可观察对象,并让 UI 对其做出反应(例如,通过隐藏标题,也许还有其他一些视图 - 这就是我要做的在片段中或与数据绑定)
我将使用我们讨论过的#2 方法,但尝试使用 LiveData。以上是关于Android MVVM UI 控件的主要内容,如果未能解决你的问题,请参考以下文章