是否可以将一个ObservableField绑定到另一个? [英] Is it possible to bind one ObservableField to another?

查看:80
本文介绍了是否可以将一个ObservableField绑定到另一个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解 Android的数据绑定库的目的是以便观察数据并在数据更改时自动更新。

I understand that the purpose of Android's data-binding library is for views to observe data and automatically update when that data changes.

问题::数据是否可以观察其他数据?例如,我可以有一个 ObservableField 取决于吗?或绑定到另一个或一组其他 ObservableField 的值?目前,我已经手动实现了此操作-每当有受养人 ObservableField 的更改,我计算了从属字段并更新了其值。

Question: Is it possible for data to observe other data? For example, can I have one ObservableField "depend on" or "bind to" the value of another or a set of other ObservableFields? Currently, I have implemented this manually - every time any of the "dependee" ObservableFields change, I compute the dependent field and update its value.

我的用例是我要所有逻辑在视图之外-所以我想将我所有的逻辑放在数据类(如果可以的话,请添加 ViewModel )。我有一个按钮,其状态要根据其他几个字段的内容设置为启用/禁用。此示例说明了我的想法。

My use-case is I want all "logic" to be outside the View - so I want to put all my logic in the "data" class (ViewModel, if I may). I have a button whose state I want to set to enabled/disabled depending on the contents of several other fields. This example illustrates what I have in mind.

我的布局文件如下

<layout>
    <data>
        <variable name="register" class="com.example.RegisterViewModel"/>
    </data>
    <LinearLayout>
        <EditText 
            android:id="@+id/edUsername" 
            android:text="@{register.username}"/>
        <EditText android:id="@+id/edPassword" />
        <EditText android:id="@+id/edConfirm" />
        <Button android:text="Register" android:enabled="@{register.isValid}" />
    </LinearLayout>
</layout>

而且,我的查看代码如下:

And, my View code is as follows:

class RegisterView extends View {
    @Override
    protected void onFinishInflate() {
        RegisterViewBinding binding = DataBindingUtil.bind(this);
        RegisterViewModel register = new RegisterViewModel();
        binding.setRegister(register);
        binding.edPassword.setOnFocusChangeListener(new OnFocusChangeListener(){
            @Override public void onFocusChange(View v, boolean hasFocus){
                register.updateUsername(edPassword.getText().toString());
            }
        });
        
        //Similarly for other fields.
    }
}

这是我的ViewModel

Here is my ViewModel

class RegisterViewModel {
    public final ObservableField<String> username = new ObservableField<>();
    private final ObservableField<String> password = new ObservableField<>();
    private final ObservableField<String> confirmPassword = new ObservableField<>();
    public final ObservableBoolean isValid;
    
    //Dependee Observables - isValid depends on all of these
    private final ObservableBoolean isUsernameValid = new ObservableBoolean();
    private final ObservableBoolean isPasswordValid = new ObservableBoolean();
    private final ObservableBoolean arePasswordsSame = new ObservableBoolean();
    
    public RegisterViewModel(){
        //Can this binding be made observable so that isValid automatically 
        //updates whenever isUsernameValid/isPasswordValid/arePasswordsSame change?
        isValid = new ObservableBoolean(isUsernameValid.get() && 
                isPasswordValid.get() && 
                arePasswordsSame.get());
        
    }
    
    public void updateUsername(String name) {
        username.set(name);
        isUsernameValid.set(ValidationUtils.validateUsername(name));
        updateDependents();
    }
    
    public void updatePassword(String pwd) {
        password.set(pwd);
        isPasswordValid.set(ValidationUtils.validatePassword(pwd));
        updateDependents();
    }
    
    public void updateConfirmPassword(String cnf) {
        confirmPassword.set(cnf);
        arePasswordsSame.set(password.get().equalsIgnoreCase(cnf.get()));
        updateDependents();
    }
    
    //Looking to avoid this altogether
    private void updateDependents() {
        isValid.set(isUsernameValid.get() && 
                isPasswordValid.get() && 
                arePasswordsSame.get());
    }
}


推荐答案

它使用Android数据绑定中的绑定语法无法对两个 ObservableField s进行数据绑定。但是,您可以将它们与代码绑定:

It is not possible to data bind two ObservableFields using binding syntax in Android data binding. However, you can bind them with code:

class RegisterViewModel {
    public final ObservableField<String> username = new ObservableField<>();
    public final ObservableField<String> password = new ObservableField<>();
    public final ObservableField<String> confirmPassword = new ObservableField<>();
    public final ObservableBoolean isValid = new ObservableBoolean();

    private boolean isUsernameValid;
    private boolean isPasswordValid;
    private boolean arePasswordsSame;

    public RegisterViewModel() {
        // You can use 3 different callbacks, but I'll use just one here
        // with 'if' statements -- it will save allocating 2 Object.
        OnPropertyChangedCallback callback = new OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(Observable sender, int propertyId) {
                if (sender == username) {
                    isUsernameValid = ValidationUtils.validateUsername(name);
                } else if (sender == password) {
                    isPasswordValid = ValidationUtils.validatePassword(pwd);
                } else if (sender == confirmPassword) {
                    arePasswordsSame = password.get()
                        .equalsIgnoreCase(confirmPassword.get());
                } else {
                    // shouldn't get here...
                }
                isValid.set(isUsernameValid && isPasswordValid && arePasswordsSame);
            }
        };

        username.addOnPropertyChangedCallback(callback);
        password.addOnPropertyChangedCallback(callback);
        confirmPassword.addOnPropertyChangedCallback(callback);
    }
}

在这里,我假设用户名,密码为空,和ConfirmPassword无效。

Here, I've assumed that empty username, password, and confirmPassword are invalid. Seemed a safe assumption.

我认为私有 ObservableField 的需求不大。 ObservableField 旨在与用户界面绑定,如果不能,则可以使用其他数据类型。如果您发现它们对于使用上述类似的回调进行内部绑定很有用,请继续使用。

I don't see a tremendous need for private ObservableFields. ObservableField was designed to be bound to by the UI and if you can't, you can use other data types. If you find them useful for internal binding using callbacks like the above, then go for it.

这篇关于是否可以将一个ObservableField绑定到另一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆