Адаптеры привязки данных Android не работают

У меня есть эти адаптеры в классе Binding Utils:

@BindingAdapter("text")
public static void bindDoubleInText(AppCompatEditText tv, Double 
value)
{
    if (tv.getText() == null) return;

    // Get the actual EditText value
    String edittextValue = tv.getText().toString();

    if (edittextValue.isEmpty())
    {
        if (value != null) tv.setText(Double.toString(value));
    }
    else
    {
        if (value != null && 
Double.parseDouble(tv.getText().toString()) != value)
            tv.setText(Double.toString(value));
    }
}

@InverseBindingAdapter(attribute = "android:text")
public static Double getDoubleFromBinding(TextView view)
{
    String string = view.getText().toString();

    return string.isEmpty() ? null : Double.parseDouble(string);
}

@BindingAdapter("text")
public static void bindIntegerInText(AppCompatEditText 
appCompatEditText, Integer value)
{
    CharSequence charSequence = appCompatEditText.getText();

    if (charSequence == null || value == null) return;

    // Get the actual EditText value
    String edittextValue = charSequence.toString();

    if (edittextValue.isEmpty() || Integer.parseInt(edittextValue) != 
value)
        appCompatEditText.setText(Integer.toString(value));
}

@InverseBindingAdapter(attribute = "android:text")
public static Integer getIntegerFromBinding(TextView view)
{
    String string = view.getText().toString();

    return string.isEmpty() ? null : Integer.parseInt(string);
}`

И это часть одного из моих XML-файлов:

<android.support.v7.widget.AppCompatEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:gravity="center_horizontal"
android:hint="dosis"
android:inputType="numberDecimal"
android:minEms="5"
android:text="@={workOrderFertilizer.dose}"/>`

Дело в том, что в Android Studio 2.2.3 версия работает отлично. Когда я обновился до Android Studio 2.3, это перестало работать, и Gradle показывает несколько ошибок. Я изменил атрибут адаптеров привязки и адаптеров обратной привязки с "android: text" на "text", но он не работает. Нечто подобное произошло и с другим пользователем в этом вопросе: привязка данных прервалась после обновления до Gradle 2.3, но разница в том, что я использую "android: текст" для привязки, поэтому ответ Джорджа Маунта мне не подходит. У кого-нибудь есть идеи? Я действительно разочарован этим, потому что я не могу обновить Android Studio из-за этой проблемы.

2 ответа

Ярлыки для двусторонней привязки, такие как android:text='@={"" + obj.val}' работать только с примитивами, а не с обёртками объектов, такими как Double и Float.

Вы можете заставить двустороннюю привязку работать с оболочками с помощью BindingAdapters. Я написал это, и они, кажется, работают хорошо:

@BindingAdapter("android:text")
public static void setDouble(TextView view, Double val) {
    if (val != null) {
        String currentValue = view.getText().toString();
        if (currentValue.length() != 0) {
            try {
                double oldVal = Double.parseDouble(currentValue);
                if (oldVal == val) {
                    return;
                }
            } catch (NumberFormatException e) {
                // that's ok, we can just set the value.
            }
        }
        view.setText(val.toString());
    }
}

@InverseBindingAdapter(attribute = "android:text")
public static Double getDouble(TextView view) {
    try {
        return Double.parseDouble(view.getText().toString());
    } catch (NumberFormatException e) {
        return null;
    }
}

С плагином Android Gradle 3.0 вы также можете использовать функции конвертации, но ввод будет немного неуклюжим, если вы не сделаете некоторое управление. Вы можете связать это так:

<EditText
    android:id="@+id/textView"
    android:text="@={Converters.doubleToString(textView, item.dose)}" .../>

и иметь преобразователи, как это:

@InverseMethod("doubleToString")
public static Double stringToDouble(TextView view, CharSequence value) {
    if (value == null) {
        return null;
    }
    try {
        return Double.parseDouble(value.toString());
    } catch (NumberFormatException e) {
        return null;
    }
}

public static CharSequence doubleToString(TextView view, Double value) {
    if (value == null) {
        return "";
    }
    String oldText = view.getText().toString();
    if (!oldText.isEmpty()) {
        try {
            double oldVal = Double.parseDouble(oldText);
            if (oldVal == value) {
                return view.getText();
            }
        } catch (NumberFormatException e) {
            // No problem. The TextView had text that wasn't formatted properly
        }
    }
    return value.toString();
}

Вам должно понравиться что-то ниже

<android.support.v7.widget.AppCompatEditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginEnd="10dp"
android:layout_marginRight="10dp"
android:gravity="center_horizontal"
android:hint="dosis"
android:inputType="numberDecimal"
android:minEms="5"
android:setText="@{workOrderFertilizer.dose}"/>

в адаптере

@BindingAdapter("setText")
public static void bindDoubleInText(AppCompatEditText tv, Object
d)
{
    Double value = (Double) d;
    if (tv.getText() == null) return;

    // Get the actual EditText value
    String edittextValue = tv.getText().toString();

    if (edittextValue.isEmpty())
    {
        if (value != null) tv.setText(Double.toString(value));
    }
    else
    {
        if (value != null && 
Double.parseDouble(tv.getText().toString()) != value)
            tv.setText(Double.toString(value));
    }
}
Другие вопросы по тегам