【问题标题】:Android Databinding, Listening changes in 2 EditTextsAndroid 数据绑定,监听 2 个 EditTexts 中的变化
【发布时间】:2018-12-17 05:27:26
【问题描述】:

我已经找到了here 的问题,但它并没有真正适合我。我有一个带有两个编辑文本的货币转换器,它们可以从 INR 转换为 USD,反之亦然。我需要使用DataBinding来监听每个Edittext的变化,并更新下一个EdittText的货币值

她的我的代码

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

和 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 中输入内容时,两者都会进入无限循环,因为两个文本更改侦听器都会在每次值更新时不断触发。我可以通过在每个EditTexts 中手动添加TextWatcher 并在设置值以避免无限循环之前暂时将textChangelistener 设置为null 来解决此问题。有没有其他有效的方法使用数据绑定来做到这一点?

【问题讨论】:

    标签: android data-binding


    【解决方案1】:

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

    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" />
    ...
    

    当然,如果您的活动需要设置您的 viewModel:

    BindingViewModel viewModel=new BindingViewModel();
        binding.setVm(viewModel);
    

    【讨论】:

    • 此方法有效。那么在这种情况下,notifyPropertyChanged 究竟如何不会导致循环呢?只有当值来自用户输入时,它才会在内部触发第二个 EditText 的文本观察器?
    • @user3339689,当您更改 EditText 中的文本时,将调用 setter 方法,在我们的例子中,notifyPropertiyChange 将调用另一个 getter 方法。所以没有理由无限循环
    猜你喜欢
    • 2018-06-10
    • 2020-10-10
    • 2013-01-05
    • 2016-05-25
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多