Bindable не получает уведомления

@Bindable
public String getFirstName() { 
    return this.firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
    notifyPropertyChanged(BR.firstName);
}

@Bindable
public String getLastName() { 
    return this.lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
    notifyPropertyChanged(BR.lastName);
}


@Bindable({"firstName", "lastName"})
public void getName() { 
    return this.firstName + ' ' + this.lastName; 
}

Приведенный выше код я взял из примера кода Google - https://developer.android.com/reference/android/databinding/Bindable

И используя его в XML, например

<TextView
    android:id="@+id/first_name"
    .....
    android:text="@{myViewModel.firstName}" />
<TextView
    android:id="@+id/last_name"
    .....
    android:text="@{myViewModel.lastName}" />
<TextView
    android:id="@+id/full_name"
    .....
    android:text="@{myViewModel.getName()}" />

Всякий раз, когда я звоню myViewModel.setFirstName("Mohammed");, он обновляет первое имя в поле зрения, но не полное имя. Даже документация глючная и ненадежная.

Другие сообщения, связанные с этой проблемой, не могут помочь, так как большинство из них имеют дело с непараметризованными Bindables.

Согласно этой строке в документе

Всякий раз, когда либо имя, либо фамилия имеют уведомление об изменении, имя также будет считаться грязным. Это не означает, что onPropertyChanged(Observable, int) будет уведомлено для BR.name, только то, что выражения привязки, содержащие имя, будут испорчены и обновлены.

Я также пытался вызвать notifyPropertyChanged(BR.name);, но это также не повлияло на результат.


person Mohammed Atif    schedule 03.07.2018    source источник


Ответы (2)


Просто взлом

public class Modal {
    private String firstName;
    private String lastName;
    private String name;

    @Bindable
    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        notifyPropertyChanged(BR.firstName);
        notifyPropertyChanged(BR.name);
    }

    @Bindable
    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
        notifyPropertyChanged(BR.lastName);
        notifyPropertyChanged(BR.name);
    }


    @Bindable
    public void getName() {
        return this.firstName + ' ' + this.lastName;
    }
}
person Khemraj Sharma    schedule 03.07.2018
comment
Извините, что прерываю вечеринку, но я нашел реальное решение. Документация у них плохая. Пришлось поломать голову, чтобы понять эту концепцию привязки данных. - person Mohammed Atif; 03.07.2018
comment
Если вы уже используете этот хак где-нибудь в своем коде, я бы порекомендовал вам взглянуть на мой ответ. Хотя это хороший рабочий хак, мне удалось найти реальное решение. - person Mohammed Atif; 03.07.2018

Итак, после тщательного анализа концепций привязки данных я обнаружил, что когда мы вызываем notifyPropertyChanged для класса BaseObservable, он фактически уведомляет свойство, а не геттеры и сеттеры.

Итак, в моем вопросе выше нет изменений в части JAVA, но в части XML требуется изменение.

<TextView
    android:id="@+id/first_name"
    .....
    android:text="@{myViewModel.firstName}" />
<TextView
    android:id="@+id/last_name"
    .....
    android:text="@{myViewModel.lastName}" />
<TextView
    android:id="@+id/full_name"
    .....
    android:text="@{myViewModel.name}" />

Поскольку я объявляю getName() как Bindable({"firstName", "lastName"}), привязка данных генерирует свойство name, поэтому мне приходится прослушивать myViewModel.name вместо myViewModel.getName() в моем XML. И нам даже не нужно уведомлять name об изменении, уведомление только firstName или lastName уведомит свойство name из-за параметризованного Bindable.

Но убедитесь, что

person Mohammed Atif    schedule 03.07.2018
comment
Круто, кстати, я не заметил, что ты используешь myViewModel.getName(). Binding не использует синтаксис имени метода, он найдет метод доступа к имени. Поэтому всегда используйте имя поля. - person Khemraj Sharma; 03.07.2018
comment
Это одна из последних вещей, которую кто-либо заметит, даже в документах не было ясности. Но если мы слушаем свойство, то только параметризованные Bindables будут работать. - person Mohammed Atif; 03.07.2018