Android MVVM。如何将复杂数据/命令从域传输到视图
简而言之,问题是:在MVVM(AAC)中,域(业务逻辑)如何管理视图层中复杂状态/数据的显示? 现在更详细 这意味着域内:1)接收、计算一些需要显示的数据;2) 状态已更改,有必要对此做出反应(隐藏/显示一组小部件、调用新片段、显示/更新进度等)。这比仅仅显示一条消息或一个对话框,或者仅仅向RecyclerView发送LiveData要困难得多 因此,像“hello world”或“2+2=4”这样的例子并不合适,它们中的一切都很清楚。在MVP中,这很简单。但在这里,我发现了MVVM的弱点 现在我做了下面的事情 通过RxJava2(作为一个选项,它可以是来自AAC的LiveData)从域到视图(通过ViewModel AAC)传递一个包含命令类型(Android MVVM。如何将复杂数据/命令从域传输到视图,android,design-patterns,mvvm,rx-java,android-architecture-components,Android,Design Patterns,Mvvm,Rx Java,Android Architecture Components,简而言之,问题是:在MVVM(AAC)中,域(业务逻辑)如何管理视图层中复杂状态/数据的显示? 现在更详细 这意味着域内:1)接收、计算一些需要显示的数据;2) 状态已更改,有必要对此做出反应(隐藏/显示一组小部件、调用新片段、显示/更新进度等)。这比仅仅显示一条消息或一个对话框,或者仅仅向RecyclerView发送LiveData要困难得多 因此,像“hello world”或“2+2=4”这样的例子并不合适,它们中的一切都很清楚。在MVP中,这很简单。但在这里,我发现了MVVM的弱点 现在
enum
)的对象,该对象具有一组用于所有场合的数据字段(当然,不同命令的不同字段)。
此外,该视图还包含一个大的开关盒
,具体取决于处理所有这些操作的命令类型
备选案文2。创建一组特定对象,然后在视图中放置一个大的if instanceof
备选案文3。将视图数据存储在ViewModel AAC中(实际上是为其准备的),并仅从域发送命令类型,然后View从ViewModel获取所有必要的数据
备选案文4。一个堆(在复杂用例的情况下)域中特定的可观察对象
,视图中的订户堆
所以:有没有更优雅的方式?可能存在某种架构模式。也许我的反射是徒劳的,这是正确的方法。
ps。1) 这里的“命令”模式并不完全适合,2)我已经实现了“状态”模式,它也不能解决问题
在MVP中,这很简单。但在这里我找到了弱者
MVVM点
这并不是MVVM的弱点,只是MVP实现和MVVM实现的区别
- 在MVP中,您创建了一组接口,让视图和演示者彼此对话李>
- 在MVVM中,您可以创建一个中介(例如,
)来桥接视图和视图模型LiveData
- 在您的UserCase中,创建一个
a来存储结果中介livedata
- 在ViewModel中,创建一个
B以观察a(即MediatorLiveData
)MediatorLiveData.addSource(a)
- 在您的视图中,观察B以反映任何UI更新
您可以在中找到具体示例。模型视图视图模型体系结构
- 视图是用户界面、布局。在Android中,这通常意味着一个活动、片段或视图持有者及其相应的膨胀XML布局文件
- 该模型是我们的业务逻辑层,它提供了与数据交互的方法
- 视图模型充当视图和模型之间的中间人,通过属性公开模型中的数据并包含UI状态。此外,它还定义了可以在单击等事件中调用的命令。视图模型包含应用程序的表示逻辑
<layout xmlns:android="...">
<data>
<variable name="vm" type="pkg.MyViewModel" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{vm.shouldShowText}"
android:text="@={vm.text}" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{vm::onButtonClick}"
android:text="@string/button"/>
</FrameLayout>
</layout>
这里我们有一个文本属性。由于我们有一个用于用户输入的EditText,我们可以使用双向数据绑定,也可以让数据绑定库将输入保存回视图模型。为此,我们创建了一个setter和一个getter,并将属性绑定到EditText的text属性,但这次在括号前使用了一个=符号,这表示库需要双向数据绑定
此外,我们只希望在模型表示需要文本输入时显示EditText。为此,我们在视图模型中提供了一个布尔属性,并将其绑定到可见性属性。为了实现这一点,我们还必须创建一个绑定适配器,它将可见性设置为false时为GONE,true时为VISIBLE
@BindingAdapter("android:visibility")
public static void setVisibility(View view, boolean visible) {
view.setVisibility(visible ? View.VISIBLE : View.GONE);
}
最后,我们希望在按下按钮时存储信息。为此,我们在视图模型中创建一个命令onButtonClick(),用于处理与模型的交互。在布局中,我们将命令绑定到t
@BindingAdapter("android:visibility")
public static void setVisibility(View view, boolean visible) {
view.setVisibility(visible ? View.VISIBLE : View.GONE);
}