具有编程用户界面定制的Android MVVM

具有编程用户界面定制的Android MVVM,android,mvvm,android-databinding,Android,Mvvm,Android Databinding,我正试图在一个带有Android数据绑定库的应用程序中确定正确的MVVM分层。与大多数示例一样,非常简单的布局通过绑定到my View模型中的方法的XML布局很好地进行抽象,以便通过可观察对象进行事件处理和模型更新。但是,通常情况下,需要通过编程(findviewbyd()…)和/或通过向字符串资源中注入样式属性等方式进行UI自定义 我应该仅仅将活动/片段视为视图的一部分,并通过数据绑定在VM和布局之间处理任何无法处理的事情,还是只使用从VM到活动/片段的接口(同时尝试将VM保持为POJO)来处

我正试图在一个带有Android数据绑定库的应用程序中确定正确的MVVM分层。与大多数示例一样,非常简单的布局通过绑定到my View模型中的方法的XML布局很好地进行抽象,以便通过可观察对象进行事件处理和模型更新。但是,通常情况下,需要通过编程(findviewbyd()…)和/或通过向字符串资源中注入样式属性等方式进行UI自定义

我应该仅仅将活动/片段视为视图的一部分,并通过数据绑定在VM和布局之间处理任何无法处理的事情,还是只使用从VM到活动/片段的接口(同时尝试将VM保持为POJO)来处理这个问题更好

--编辑:示例1--


在同一字符串中呈现具有多种颜色的文本视图:我最初是如何在字符串资源中包装CDATA和字体标记,并使用findViewById().setText(Html.fromHtml(getString(..))呈现的。我已经修改了我的布局,改为在我的VM中绑定为android:text=“@{viewModel.text1}”,它对我的片段调用一个接口方法,该片段返回Html.fromHtml(text),我的VM返回布局的一个span。考虑到严格的MVVM,我可能不会以这种方式定义VM,因此感觉有点粗糙。

如果有数据绑定,就不必使用findviewbyd()。大多数东西都可以通过数据绑定进行绑定,因为目前它是双向的。请参阅以下网站的最新更新:

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


对于其他更改,您可以编写自己的BindingAdapter。我更喜欢保持VM干净的POJO。

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

例如,如果您希望TextView根据在ViewModel中做出的决定显示字符串a或B,则可以为您创建一个Android资源抽象界面,并将该界面从视图传递到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>


但是这是一个非常激进的方法。我建议你总是考虑你的VIEW模型是否仍然是作证的。例如,当你在VIEW模型中从R类中访问资源ID时,你仍然可以创建JUnit测试。但是另一方面,你不应该在视图模型中使用HTML.FROMHTML,因为你将得到一个未被嘲笑的错误。对于回答。正如我提到的,我确实有简单的事件处理(例如onClick)和模型更新(例如通过TextWatcher)已经绑定到布局XML和VM中。我用一个示例更新了这个问题,其中我正在以一种不太标准的方式修改UI。对这个示例有何想法?