双向数据绑定无限循环

时间:2016-09-12 14:03:27

标签: android infinite-loop android-databinding

我有一个项目列表。在每个项目的行中,我有两个并排的EditTexts。 EditText-2取决于EditText-1的值。此列表与HashMap<String, ItemValues>

中的数据绑定值绑定

例如:

Total     _____1000____
Item A    __1__ __200__
Item B    __1__ __200__
Item C    __1__ __200__
Item D    __2__ __400__

第一个EditText是共享,第二个值是根据总数和份额计算的值。因此,在示例中,如果我更改任何1个共享,则将更改所有值。因此,在示例中显示,共享no = = 1 + 1 + 1 + 2 = 5.因此每股数量= 1000/5 = 200并计算并显示在下一个EditText中。

我已将这些值绑定到双向数据绑定,如下所示:

因为,这是一个double值,我为此添加了2个绑定适配器:

@BindingAdapter("android:text")
public static void setShareValue(EditText editText, double share) {
    if (share != 0) {
        editText.setText(String.valueOf(share));
    } else {
        editText.setText("");
    }
}

@InverseBindingAdapter(attribute = "android:text")
public static double getShareValue(EditText editText) {
    String value = editText.getText().toString();
    if (!value.isEmpty()) {
        return Double.valueOf(value);
    } else
        return 0;
}

现在,要计算新值,我需要在更改任何共享值后重新计算整个事物。因此,我添加了android:onTextChagned方法来更新计算。但它让我无限循环。

<EditText
    android:text="@={items[id].share}"
    android:onTextChanged="handler.needToUpdateCalculations"
    .... />

public void needToUpdateCalculations(CharSequence charSequence, int i, int i1, int i2) {
    updateCalculations();
}

这会得到一个infinete循环,因为当数据发生变化时,它会反弹到EditText,并且每个EditText都附加一个onTextChanged,它会再次触发,它将变得非常大 - 无限循环。

它还会更新自身的值,最后也会丢失光标。

我还尝试了其他几种方法,例如在焦点时添加TextWatcher,在丢失焦点时删除。但至少它会自我更新并且会松开光标或无限循环。

无法解决此问题。感谢您查看此问题。

修改

我尝试过以下方法。但是,它不允许我输入.(句号)。

@BindingAdapter("android:text")
public static void setDoubleValue(EditText editText, double value) {
    DecimalFormat decimalFormat = new DecimalFormat("0.##");
    String newValue = decimalFormat.format(value);
    String currentText = editText.getText().toString();

    if (!currentText.equals(newValue)) {
        editText.setText("");
        editText.append(newValue);
    }
}

1 个答案:

答案 0 :(得分:1)

你说的理由是正确的,它肯定会产生无限循环。并且有一种方法可以摆脱这个问题的无限循环,android官方提供了一种方法(但它不是很明显。)(https://developer.android.com/topic/libraries/data-binding/index.html#custom_setters

  

绑定适配器方法可以选择在其中使用旧值   处理程序。采用旧值和新值的方法应该都是旧的   首先是属性的值,然后是新值:

    @BindingAdapter("android:paddingLeft")
    public static void setPaddingLeft(View view, int oldPadding, int newPadding) {
       if (oldPadding != newPadding) {
           view.setPadding(newPadding,
                           view.getPaddingTop(),
                           view.getPaddingRight(),
                           view.getPaddingBottom());
       }
    }

您可以使用旧值和新值比较来有条件地调用setText函数。

@BindingAdapter("android:text")
public static void setShareValue(EditText editText, double oldShare,double newShare) {
    if(oldShare != newShare)
    {
        if (newShare!= 0) {
            editText.setText(String.valueOf(newShare));
        } else {
            editText.setText("");
        }
    }
}