Ph0en1x Ph0en1x - 3 months ago 13
Android Question

android 2 way data binding example don't work as described

I read this article about 2 way android data binding

I noticed that code is a bit vague and decide to implement workable example and put it on github, so other guys will be much easier to dive in it. But going according instructions provided in this article I wasn't able make it work.

In my example I just have main activity with switcher, and custom control, also with switcher. So, when I checking main switcher it refresh all the stuff properly and work as expected, but however when I check/uncheck internal switcher, it dosen't affect main viewmodel and anything in activity - so 2 way binding not working.

Please, help me find the reason why this happen and fix the problem.




Code fixed and now worked as expected in Android Studio 2.2 beta 1 at least.

Link to the code sample on github

Answer

You almost hooked up everything properly. In CustomSwitcher, there was no notification when the inner switcher's value changed. You must listen for that change and call the onValChanged callback.

Here is your code:

public CustomSwitcher(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.binding = CustomSwitcherBinding.inflate(LayoutInflater.from(context), this, true);
}

public void setVm(boolean vmVal){
    this.vm = vmVal;
    this.binding.setItem(vm);
}

The inflated binding doesn't directly notify the custom switcher, so you must listen for the event. Then you'll have to call the listener. You must also avoid the infinite loop of notifying the same value over-and-over again by assuring that you're not setting the same value as already exists.

public CustomSwitcher(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.binding = CustomSwitcherBinding.inflate(LayoutInflater.from(context), this, true);
    this.binding.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(Observable sender, int propertyId) {
            if (propertyId == BR.item) {
                setVm(binding.getItem());
            }
        }
    });
}

public void setVm(boolean vmVal){
    if (vmVal != this.vm) {
        this.vm = vmVal;
        this.binding.setItem(vm);
        if (this.onValChanged != null) {
            this.onValChanged.onValChanged(this, vmVal);
        }
    }
}