3

我正在尝试使用 Android 数据绑定库在应用程序中确定正确的 MVVM 分层。非常简单的布局,就像在大多数示例中一样,很好地抽象了 XML 布局绑定到我的 View Model 中的方法,用于通过 observables 进行事件处理和模型更新。但是,通常情况下,需要以编程方式(findViewById()...)和/或通过将样式属性注入字符串资源等方式进行 UI 自定义。

我是否应该将 Activity/Fragment 也视为 View 的一部分,并通过数据绑定在 VM 和布局之间做任何无法处理的事情,还是只使用从 VM 到 Activity/Fragment 的接口来处理这个更好(同时试图让VM保持POJO)?

-- 编辑:示例 1 --

在同一字符串中渲染具有多种颜色的 TextView:我最初的实现方式是将 CDATA 和字体标签包装在字符串资源中,并使用 findViewById().setText(Html.fromHtml(getString(..))) 进行渲染。我修改了我的布局,改为在我的 VM 中绑定为 android:text="@{viewModel.text1}",它调用我的片段的接口方法返回 Html.fromHtml(text),我的 VM 返回一个 Spanned to布局。考虑到严格的 MVVM,我可能不会这样定义 VM,所以感觉有点 hacky。

4

2 回答 2

1

根据经验,我不会在需要 Android 上下文的 ViewModel 中放入任何东西。另一方面,所有逻辑都应该位于 ViewModel 中,以便您可以对其进行单元测试。

例如,如果您希望 TextView 根据在 ViewModel 中做出的决定显示字符串 A 或 B,您可以为您创建一个作为 Android 资源抽象的接口,并将此接口从 View 传递到 ViewModel。

public MyViewModel {

 private MyStrings strings;

 public MyViewModel(MyStrings strings) { 
   this.strings = strings;
 }

 public String getMyString() {
   return becauseOfReasons() ? strings.getA() : strings.getB();
 }

  public interface MyStrings {
   String getA();
   String getB();
  } 
}

对于您的示例,您想以编程方式使用 Html.fromHtml。Android 数据绑定库的真正优点在于您可以从 xml 使用访问 Html.fromHtml()。因此,在您的情况下,xml 可能如下所示:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
  <data>

    <import type="android.text.Html"/>

    <variable
        name="viewModel"
        type="some.package.MyViewModel"/>

  </data>

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{Html.fromHtml(viewModel.myString)}"/>
</layout>

然而,这是一种相当激进的方法。我建议始终考虑您的 ViewModel 是否仍然可测试。例如,当您从 ViewModel 中的 R 类访问资源 id 时,您仍然可以创建 JUnit 测试。但另一方面,您不应该在 ViewModel 中使用 Html.fromHtml ,因为您会得到一个未模拟的错误。

于 2016-12-19T10:34:07.370 回答
0

如果您有数据绑定,则不必使用 findViewById()。大多数东西都可以通过数据绑定来绑定,因为它目前是双向的。查看最新更新: https ://developer.android.com/tools/data-binding/guide.html

您可以在 XML 布局中直接将字符串属性与 TextWatcher 绑定在一起。你可以对 android:onClick 做同样的事情。此外,还有一种方法可以通过生成的类访问数据绑定中的类,如下所示:YourClassBinding.nameOfYourView(假设您的布局名称是 your_class.xml 并包含一个带有 @id/name_of_your_view 的视图。

对于其他更改,您可以编写自己的 BindingAdapter。我宁愿保持 VM 清洁 POJO。

于 2015-08-07T21:54:34.117 回答