1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | [code language="java"]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); } [/code] |
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
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | [code language="java"] 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(); } } [/code] |
..and the more readable MainActivity-constructor:
1 2 3 4 5 6 7 8 | [code language="java"] public MainViewModel() { OnPropertyChangedCallback buttonUpdater = new BindingCallbackAdapter(this::updateButtonEnabledState); firstName.addOnPropertyChangedCallback(buttonUpdater); lastName.addOnPropertyChangedCallback(buttonUpdater); } [/code] |
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.