Android: 数据绑定文本未更新

Android: Data Binding Text not Updating

我希望用户在 EditText 中输入他们的姓名并在 TextView 中显示 Hello {name}。当我将 TextView 的文本设置为可观察的 属性 (user.firstName) 时,文本会更新。即使我将文本设置为模型的 toString() 方法,它仍然可以正常工作。但是,如果我改为使用 viewModel.hello,则文本不会更新。我错过了什么?

型号:

public class User extends BaseObservable {
    public String firstName;
    public String lastName;

    public User(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

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

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

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

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

    @Override
    public String toString() {
        return getFirstName() + " " + getLastName();
    }
}

视图模型:

public class ViewModel {
    public  User user;

    public ViewModel() {
        user = new User("", "");
    }

    public String hello() {
        return "Hello " + user.toString();
    }

    public TextWatcher userNameTextWatcher() {
        return new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void afterTextChanged(Editable editable) {
                if (editable.toString().length() == 0) {
                    user.setFirstName("");
                    user.setLastName("");
                    user.notifyChange();
                    return;
                }
                String[] name = editable.toString().split(" ");
                if (name.length == 1) {
                    user.setFirstName(name[0]);
                    user.setLastName("");
                    user.notifyChange();
                    return;
                }
                String firstName = name[0] + " ";
                for (int i = 0; i < name.length - 2; i++) {
                    firstName = firstName + " " + name[i] + " ";
                }
                user.setFirstName(firstName);
                user.setLastName(name[name.length - 1]);
                user.notifyChange();
            }
        };
    }
}

布局:

<data>
    <variable
        name="viewModel"
        type=".ViewModel"/>
</data>

<TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:text="@{viewModel.hello}"/>

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView"
        android:layout_marginTop="8dp"
        app:addEditTextWatcher="@{viewModel.userNameTextWatcher}"/>

一个问题是您的 ViewModel 不可观察,因此对 hello() 的更改不会反映在模型中。由于它是一个可观察的字段,您还可以将 ObservableField 用于 hello 字符串,但我将使用 Observable ViewModel 对其进行演示。

public class ViewModel extends BaseObservable {
    public final User user;

    public ViewModel() {
        user = new User("", "");
        user.addOnPropertyChangedCallback(new OnPropertyChangedCallback {
            @Override
            public void onPropertyChanged(Observable sender, int property) {
                if (property == BR.firstName || property == BR.lastName) {
                    notifyPropertyChanged(ViewModel.this, BR.hello);
                }
            }
        });
    }

    @Bindable
    public String hello() {
        return "Hello " + user.toString();
    }

    public TextWatcher userNameTextWatcher() {
        return new TextWatcher() { ... }
    };
}

}

但我认为直接在 XML 中监听对 User 的更改会容易得多,而不用担心让 ViewModel 可观察:

 <data>
     <variable
         name="viewModel"
         type=".ViewModel"/>
 </data>

 <TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    tools:text="@{@string/hello(viewModel.user.firstName, viewModel.user.lastName)}"/>

<EditText
    android:id="@+id/editText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/textView"
    android:layout_marginTop="8dp"
    app:addEditTextWatcher="@{viewModel.userNameTextWatcher}"/>

并且您将拥有一个字符串资源:

<string name="hello">Hello %1$s %2$s</string>