Two-way data-binding infinite loop

大城市里の小女人 提交于 2019-12-12 02:40:06

问题


I have a list of items. In each item's row I have 2 EditTexts side-by-side. EditText-2 depends on EditText-1's value. This list is bound with data-binding values in HashMap<String, ItemValues>

For Example:

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

First EditText is the share and the second value is its value calculated based on total and share. So, in example if I change any 1 share, all the values will be changed. So, shown in example total no of shares are = 1+1+1+2 = 5. So amount per share = 1000/5 = 200 and is calculated and shown in next EditText.

I have bound this values with two-way data binding like this:

As, this is a double value, I have added 2 binding adapters for this like this:

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

Now, to calculate new values, I need to re-calculate whole thing after any share value is changed. So, I added android:onTextChagned method to update Calculations. But it gets me an infinite loop.

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

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

This gets an infinete loop because when data changes, it is rebound to the EditText, and each EditText has an onTextChanged attached it will fire again and it will get really large - infinite loop.

It also updates the value of itself, ended up loosing the cursor as well.

I have also tried several other methods like adding TextWatcher when on focus and removing when losses focus. But at least it will update it self and will loose the cursor or infinite loop.

Unable to figure this problem out. Thank you for looking into this problem.

EDIT:

I have tried with the below method. But, it doesn't allow me to enter . (period).

@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:


The reason you stated is correct and it will make a infinite loop definitely. And there is a way to get out from the infinite loop of this problem, android official provided a way to do so (But it is not quite obvious.)(https://developer.android.com/topic/libraries/data-binding/index.html#custom_setters)

Binding adapter methods may optionally take the old values in their handlers. A method taking old and new values should have all old values for the attributes come first, followed by the new values:

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

You can use the old value and new value comparison to make the setText function called conditionally.

@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("");
        }
    }
}


来源:https://stackoverflow.com/questions/39452210/two-way-data-binding-infinite-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!