【问题标题】:Android MVVM UI controlAndroid MVVM UI 控件
【发布时间】:2020-11-26 11:35:11
【问题描述】:

我开始在 Android 上使用 LiveData 学习 MVVM。我认为显示和更新基本数据对我来说很清楚。我很难找到最佳实践的主题是控制 UI。

假设我有一个基本的用户界面,例如一个表单。它有几个 EditTextViews 来输入数据。最后它还有一个开关。如果它是ON,则会显示更多的 EditTextViews 来填充。当它OFF时,它们当然消失了。

我的问题是在哪里实现这个逻辑?

  1. 在活动/片段代码中?然后业务逻辑将涉及到 MVVM 的 VIEW 部分(我觉得不太好)。

  2. 在视图模型中?然后业务逻辑将存在于一个,比如说,数据缓存中。这样我就必须在 ViewModel 中创建一堆 boolean getter 来计算单独视图可见性的值。然后在我的 Activity 中的 LiveData 更改订阅块中,我需要读取所有这些值并一一设置视图的可见性。

  3. 在单独的 Service/Helper/Util 类中?这与 #2 的解决方案相同,只是从 ViewModel 中提取的逻辑。

这里的最佳做法是什么?不过,同样的问题可以提出用户输入验证的主题(我猜这些领域有很多)。

【问题讨论】:

  • 开/关状态是否会影响 UI 可见性以外的其他内容?如果没有 UI,它在业务逻辑中的作用是什么?
  • 当它打开时,业务逻辑分别填充 POJO 中的字段,当它关闭时,相同的字段将被留空/清除。例如,如果Under Age开关打开,用户必须输入法定代表人的数据(母亲姓名等),这些数据需要保存。
  • 按照我的理解,它是由 UI(用户单击按钮)驱动的,而不是从其他 POJO 属性派生的,例如出生日期VS现在?如果用户打开按钮,填写字段并将其关闭,POJO 应该有空值,无论 UI 中的字段不是空的,对吗?
  • 正确。是的,我现在知道这个例子不是最好的。如您所述,在大多数用例中,必须从出生日期和当前日期计算未成年人。这只是一个场景的快速示例,有时需要显示一些 UI 组件,有时需要消失。

标签: android mvvm visibility


【解决方案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。
猜你喜欢
  • 1970-01-01
  • 2011-07-17
  • 1970-01-01
  • 2011-03-30
  • 1970-01-01
  • 2018-08-08
  • 1970-01-01
  • 2014-07-19
  • 1970-01-01
相关资源
最近更新 更多