用于带参数的方法的Android双向数据绑定

时间:2017-06-26 21:36:59

标签: android android-databinding inverse two-way two-way-binding

模型的Setter和getter方法有一个参数,如下所示:

schemas.enable

XML看起来像这样:

public int getPrice(Object key) {
}

public void setPrice(Object key, int price) {
}

机器人:文本=" @ = {shipper.getPrice(priceKey)}"

构建期间的编译器错误说我们应该使用@InverseMethod注释。 我尝试这样的事情:

<EditText
android:id="@+id/edtPrice"
style="@style/CreateShipperItemValueEditTextView"
android:layout_centerVertical="true"
android:hint="@string/hint_price"
android:inputType="number"
android:maxLines="1"
android:text="@={shipper.getPrice(priceKey)}"/>

但在这种情况下,我有下一个错误。

@InverseMethod(value = "getPrice")
@Override
public void setPrice(Object key, int price) {
    super.setPrice(key, price);
}

所以我很高兴在这里很好地解释整个流程。感谢

2 个答案:

答案 0 :(得分:4)

很高兴看到您正在使用Android Studio 3.0中提供的新InverseMethod。

您正在使用与方法的双向数据绑定,并且表达式必须了解在用户修改文本时如何设置值。该用途适用于转换方法,因此我不知道这是否适用于您的情况。

基本上,数据绑定在将文本设置为View时使用这样的代码:

EditText edit = binding.edtPrice;
edit.setText(shipper.getPrice(priceKey));

当文字发生变化时,你要求它这样做:

EditText edit = binding.edtPrice;
priceKey = shipper.setPrice(priceKey, edit.getText());

这显然不起作用,它会给你一个错误。

有两件事是错的,真的。第一个是getPrice()返回int而不是CharSequenceString。第二个是setPrice()并没有真正进行转换 - 它需要不同数量的参数并返回void

在您的情况下,您不是要尝试将priceKey转换为整数;您正试图访问某种地图中的值。有几种方法可以解决这个问题。我认为最简单的方法是直接在模型中使用地图。在这里,我假设您有一个最终字段,但您可以使用getter和setter将其作为属性返回:

public class ShipperModel {
    public final ObservableArrayMap<Object, Integer> price = new ObservableArrayMap<>();
    //...
}

然后在你的表达式中:

<EditText android:text="@={`` + shipper.price[priceKey]}" .../>

如果您想要自定义转化,可以这样做:

@InverseMethod("convertToPrice")
public String convertFromPrice(Object key, int price) {
    //...
}

public int convertToPrice(Object key, String text) {
    //...
}

然后你会在表达式中传递price对象:

<EditText android:text="@={shipper.convertFromPrice(priceKey, shipper.price)}" .../>

我会简化转换方法,使它们在我的应用程序中可重用,只需将整数转换为String并返回:

public class Converters {
  @InverseMethod("fromPrice")
  public static final int toPrice(String text) {
      //...
  }

  public static final String fromPrice(int price) {
    //...
  }
}

然后表达式为:

<EditText android:text="@={Converters.fromPrice(shipper.price[priceKey])}" .../>

答案 1 :(得分:2)

在这种情况下,不要编写自己的绑定方法,而应考虑使用ObservableMap

public final ObservableMap<Object, Integer> price = new ObservableArrayMap<>();

<EditText
    android:id="@+id/edtPrice"
    style="@style/CreateShipperItemValueEditTextView"
    android:layout_centerVertical="true"
    android:hint="@string/hint_price"
    android:inputType="number"
    android:maxLines="1"
    android:text="@={shipper.price[priceKey]}"/>

但问题是将文本值(CharSequence)转换为映射值(int)。为此,您需要@InverseMethod。在你的情况下,这样的方法是不够的。因此,您需要提供@InverseBindingAdapter

@InverseBindingAdapter(attribute = "android:text", event = "android:textAttrChanged")
public static Integer convertTextToInteger(EditText view) {
    String text = view.getText().toString();
    return text.isEmpty() ? null : Integer.parseInt(text);
}

此外,您必须提供@BindingConversion@BindingAdapter来将整数映射到CharSequence以便首先设置文字。

@BindingConversion
public static CharSequence convertMyClass(Integer i) {
    return i == null ? null : i.toString();
}