Android数据绑定,在2个编辑文本中收听更改

Android数据绑定,在2个编辑文本中收听更改,android,data-binding,Android,Data Binding,我已经找到了这个问题,但它对我来说并不奏效。我有一个货币转换器和两个编辑文本,从印度卢比转换为美元,反之亦然。我需要使用数据绑定来侦听每个Edittext的更改,并更新下一个Edittext的货币值 她的密码是我的 public class BindingViewModel extends BaseObservable { public ObservableField<Double> inr = new ObservableField<>(); public Observ

我已经找到了这个问题,但它对我来说并不奏效。我有一个货币转换器和两个编辑文本,从印度卢比转换为美元,反之亦然。我需要使用数据绑定来侦听每个Edittext的更改,并更新下一个Edittext的货币值

她的密码是我的

public class BindingViewModel extends BaseObservable {
public ObservableField<Double> inr = new ObservableField<>();
public ObservableField<Double> dollar = new ObservableField<>();

public void onINRTextChanged(CharSequence s, int start, int before, int count) {
    double aDouble = Double.parseDouble(s.toString());
    dollar.set(aDouble * 0.014);
}

public void onDOLLARTextChanged(CharSequence s, int start, int before, int count) {
    Log.d("tag", "onTextChanged " + s);
    double aDouble = Double.parseDouble(s.toString());
    inr.set(71.92 * aDouble);
 }
}
公共类BindingViewModel扩展了BaseObservable{
公共可观察字段inr=新可观察字段();
公共可观察字段美元=新可观察字段();
public void onINRTextChanged(字符序列、int start、int before、int count){
double-aDouble=double.parseDouble(s.toString());
美元/套(双倍*0.014);
}
公共void onDOLLARTextChanged(字符序列,int start,int before,int count){
Log.d(“标记”、“onTextChanged”+s);
double-aDouble=double.parseDouble(s.toString());
印度卢比(71.92*双倍);
}
}
和XML

<?xml version="1.0" encoding="utf-8"?>
<layout>

<data>

    <variable
        name="vm"
        type="android.com.tasks.BindinfViewModel" />
</data>

<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/inr"
        android:layout_width="108dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="8dp"
        android:ems="10"
        android:inputType="number"
        android:onTextChanged="@{vm.onDOLLARTextChanged}"
        android:text="@{String.valueOf(vm.inr)}"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.17"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/dollar"
        android:layout_width="108dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="8dp"
        android:ems="10"
        android:inputType="number"
        android:onTextChanged="@{vm.onINRTextChanged}"
        android:text="@{String.valueOf(vm.dollar)}"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/inr"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="INR"
        app:layout_constraintEnd_toEndOf="@+id/inr"
        app:layout_constraintStart_toStartOf="@+id/inr"
        app:layout_constraintTop_toBottomOf="@+id/inr" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="DOLLAR"
        app:layout_constraintEnd_toEndOf="@+id/dollar"
        app:layout_constraintStart_toStartOf="@+id/dollar"
        app:layout_constraintTop_toBottomOf="@+id/dollar" />
</android.support.constraint.ConstraintLayout>
</layout>


在这里,每当我在任何一个EditText中输入内容时,这两个文本都将进入一个无限循环,因为两个文本更改侦听器在每次值更新时都会不断触发。我可以通过手动将
TextWatcher
添加到每个
editText
并在设置值之前临时将textChangelistener设置为
null
来解决此问题,以避免无限循环。使用数据绑定还有其他有效的方法吗?

我建议您使用双向绑定。您可以为如下字段编写setter和getter,然后使用
android:text=“@={fieldName}”
而不是
android:text=“@{fieldName}”
。 您的模型类可能如下所示:

public class BindingViewModel extends BaseObservable {
public Double inr = 0.0;
public Double dollar = 0.0;

@Bindable
public String getInrString() {
    String inrString = String.valueOf(inr);
    if (inrString.endsWith(".0"))
        return inrString.substring(0, inrString.length() - 2);
    return inrString;
}

public void setInrString(String inrString) {
    if (inrString != null && !inrString.isEmpty()) {
        double newInr = Double.parseDouble(inrString);
        if (this.inr != newInr) {
            this.inr = newInr;
            dollar = inr * 0.014;
        }
    } else {
        inr = 0.0;
        dollar = 0.0;
    }
    notifyPropertyChanged(BR.dollarString);
}

@Bindable
public String getDollarString() {
    String dollarString = String.valueOf(dollar);
    if (dollarString.endsWith(".0"))
        return dollarString.substring(0, dollarString.length() - 2);
    return dollarString;
}

public void setDollarString(String dollarString) {
    if (dollarString != null && !dollarString.isEmpty()) {
        double newDollar = Double.parseDouble(dollarString);
        if (this.dollar != newDollar) {
            this.dollar = newDollar;
            inr = dollar * 71.92;
        }
    } else {
        inr = 0.0;
        dollar = 0.0;
    }
    notifyPropertyChanged(BR.inrString);
}
}
然后您可以布局XML:

<layout>
<data>
    <variable
        name="vm"
        type="com.BindingViewModel" />
</data>

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/inr"
        android:layout_width="108dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="8dp"
        android:ems="10"
        android:inputType="number"
        android:text="@={vm.inrString}"
        android:selectAllOnFocus="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.17"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/dollar"
        android:layout_width="108dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginBottom="8dp"
        android:ems="10"
        android:inputType="number"
        android:text="@={vm.dollarString}"
        android:selectAllOnFocus="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/inr"
        app:layout_constraintTop_toTopOf="parent" />
...

这种方法有效。那么,在这种情况下,
notifyPropertyChanged
如何不引起循环呢?只有当值来自用户输入时,它才会在内部触发第二个EditText的文本监视程序?@user3339689,当您更改EditText中的文本时,将调用setter方法,在我们的例子中,NotifyPropertyChange将调用另一个getter方法。因此,没有理由使用无限循环
BindingViewModel viewModel=new BindingViewModel();
    binding.setVm(viewModel);