Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android MVVM。如何将复杂数据/命令从域传输到视图_Android_Design Patterns_Mvvm_Rx Java_Android Architecture Components - Fatal编程技术网

Android MVVM。如何将复杂数据/命令从域传输到视图

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的弱点 现在

简而言之,问题是:在MVVM(AAC)中,域(业务逻辑)如何管理视图层中复杂状态/数据的显示?

现在更详细

这意味着域内:1)接收、计算一些需要显示的数据;2) 状态已更改,有必要对此做出反应(隐藏/显示一组小部件、调用新片段、显示/更新进度等)。这比仅仅显示一条消息或一个对话框,或者仅仅向RecyclerView发送LiveData要困难得多

因此,像“hello world”或“2+2=4”这样的例子并不合适,它们中的一切都很清楚。在MVP中,这很简单。但在这里,我发现了MVVM的弱点

现在我做了下面的事情

通过RxJava2(作为一个选项,它可以是来自AAC的LiveData)从域到视图(通过ViewModel AAC)传递一个包含命令类型(
enum
)的对象,该对象具有一组用于所有场合的数据字段(当然,不同命令的不同字段)。 此外,该视图还包含一个大的
开关盒
,具体取决于处理所有这些操作的命令类型

备选案文2。创建一组特定对象,然后在视图中放置一个大的
if instanceof

备选案文3。将视图数据存储在ViewModel AAC中(实际上是为其准备的),并仅从域发送命令类型,然后View从ViewModel获取所有必要的数据

备选案文4。一个堆(在复杂用例的情况下)域中特定的
可观察对象
,视图中的
订户堆

所以:有没有更优雅的方式?可能存在某种架构模式。也许我的反射是徒劳的,这是正确的方法。

ps。1) 这里的“命令”模式并不完全适合,2)我已经实现了“状态”模式,它也不能解决问题

在MVP中,这很简单。但在这里我找到了弱者 MVVM点

这并不是MVVM的弱点,只是MVP实现和MVVM实现的区别

  • 在MVP中,您创建了一组接口,让视图和演示者彼此对话
  • 在MVVM中,您可以创建一个中介(例如,
    LiveData
    )来桥接视图和视图模型
IMHO,你可以:

  • 在您的UserCase中,创建一个
    中介livedata
    a来存储结果
  • 在ViewModel中,创建一个
    MediatorLiveData
    B以观察a(即
    MediatorLiveData.addSource(a)
  • 在您的视图中,观察B以反映任何UI更新

您可以在中找到具体示例。

模型视图视图模型体系结构

  • 视图是用户界面、布局。在Android中,这通常意味着一个活动、片段或视图持有者及其相应的膨胀XML布局文件
  • 该模型是我们的业务逻辑层,它提供了与数据交互的方法
  • 视图模型充当视图和模型之间的中间人,通过属性公开模型中的数据并包含UI状态。此外,它还定义了可以在单击等事件中调用的命令。视图模型包含应用程序的表示逻辑
在MVVM架构模式中,视图和视图模型主要通过数据绑定进行交互。理想情况下,视图和视图模型不应该相互了解。绑定应该是视图和视图模型之间的粘合剂,并在两个方向上处理大部分内容。然而,在安卓系统中,它们不能真正独立:

  • 您必须保存和恢复状态,但该状态现在位于视图模型中
  • 您需要将生命周期事件告知视图模型
  • 您可能会遇到需要直接调用视图方法的情况
  • 对于这些情况,视图和视图模型都应该实现接口,然后在必要时通过命令进行通信。但是,在几乎所有情况下,只需要视图模型的接口,因为数据绑定库处理与视图的交互,并且可以使用自定义组件(例如,当需要上下文时)

    视图模型也会更新模型,例如,通过向数据库添加新元素或更新现有元素。它还用于从模型中获取数据。理想情况下,模型还应该将更改通知视图模型,但这取决于实现

    现在,一般来说,视图和视图模型的分离使得表示逻辑易于测试,并且从长远来看有助于维护。与数据绑定库一起,这意味着更少的代码和更干净的代码

    示例:

      <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);
    }