VGTech is a blog where the developers and devops of Norways most visited website share code and tricks of the trade… Read more



Are you brilliant? We're hiring. Read more

Two way data binding without RxJava

Android

A couple of weeks ago, this article by Radosław Piekarz got some tracktion on /r/androiddev. While I am a fan of RxJava myself we use it extensively in our apps at VG.no, I feel this example was not the best use case for it. As others point out in the comment field, this can easily be solved without RxJava. Here is how:

Show code
public MainViewModel() {
    OnPropertyChangedCallback buttonUpdater = new OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(Observable sender, int propertyId) {
            updateButtonEnabledState();
        };
    };
    firstName.addOnPropertyChangedCallback(buttonUpdater);
    lastName.addOnPropertyChangedCallback(buttonUpdater);
}

private void updateButtonEnabledState() {
    boolean enable = StringUtils.isNotNullOrEmpty(firstName.get()) && StringUtils.isNotNullOrEmpty(lastName.get());
    helloButtonEnabled.set(enable);
}

What I’ve done is recoded the constructor of the viewmodel for MainActivity to hook onto the OnPropertyChanged callback of the ObservableFields for the two TextViews directly, instead of going through the hoop of RxUtils.toObservable.

You can furthermore clean up the code by writing an adapter for the OnPropertyChanged callback, which as it is is not very lambda-friendly. Introducing the helper class BindingCallbackAdapter:

Show code
public class BindingCallbackAdapter extends Observable.OnPropertyChangedCallback {
    private Callback mCallback;

    public BindingCallbackAdapter(BindingCallbackAdapter.Callback callback) {
        if (callback == null) throw new IllegalArgumentException("Callback cannot be null");
        mCallback = callback;
    }

    @Override
    public void onPropertyChanged(Observable sender, int propertyId) {
        mCallback.onChanged();
    }

    public interface Callback {
        void onChanged();
    }
}

..and the more readable MainActivity-constructor:

Show code

public MainViewModel() {
    OnPropertyChangedCallback buttonUpdater = new BindingCallbackAdapter(this::updateButtonEnabledState);
    firstName.addOnPropertyChangedCallback(buttonUpdater);
    lastName.addOnPropertyChangedCallback(buttonUpdater);
}

See full fork at github.

While I’m sure the author of the original article is aware of the possibility of this implementation, I’m afraid that too many blog posts about “RxJava for everything” spreads antipatterns. I do understand that there are cases where this could be a good pattern, for example if you need to compose the onPropertyChanged events in more complex Rx-flows, but this concrete use case is not one.

Android developer at VG


0 comments

    Leave your comment