17

I have developed app base on android data binding library: https://developer.android.com/topic/libraries/data-binding/index.html

class SignInViewModel extends BaseObservable {

    @Bindable
    public String getLogin() {
        return login;
    }

    @Bindable
    public String getPassword() {
        return password;
    }
}

and now I want to use ViewModelProviders from new library: https://developer.android.com/topic/libraries/architecture/guide.html

SignInViewModel signInViewModel = ViewModelProviders.of(this).get(SignInViewModel.class);

How it combine? any idea? or should be combined these two libraries?

Edit

I change to:

class SignInViewModel extends ViewModel {
   public ObservableField<String> login = new ObservableField<>("");

    public ObservableField<String> password = new ObservableField<>("");
}

and now compiles, but question is: is it right way?

yennsarah
  • 5,467
  • 2
  • 27
  • 48
LunaVulpo
  • 3,043
  • 5
  • 30
  • 58
  • I have found an [article](http://bytes.schibsted.com/data-binding-android-architecture-components-preview/) about this topic. Short answer, there is currently no 'right' way and we may have to wait for some news from the databinding team theirselves. – yennsarah May 23 '17 at 07:40

4 Answers4

15

It's a known incompatibility. You can't extend BaseObservable and AndroidViewModel at the same time, so you can't use @Bindable making two-way data binding impossible*.

This will be fixed after arch components 1.0 final (on the data binding side).

*Edit: You can make your own ObservableViewModel: https://gist.github.com/JoseAlcerreca/4b66f9953d50b483d80e6b9ad7172685

Jose Alcérreca
  • 1,809
  • 17
  • 20
  • So as a workaround the solution with using ObservableField is correct approach? – LunaVulpo May 25 '17 at 14:52
  • 1
    Yes, if you can restrict to using `ObservableField`s, you're fine. – Jose Alcérreca May 26 '17 at 12:18
  • Thanks this really saved me, I was switching out my `BaseOverable` view models for `AndroidViewModel` but ran into problems as my app is form heavy and uses a lot or two-way data binding. I made the form fields use `ObservableField` and kept `LiveData` for everything else for the activity to observe. – Nic Bell Aug 22 '17 at 20:25
  • 1
    @JoseAlcérreca now that Architecture Components are in 1.0 I don't see any differences when it comes to combining them with DataBinding or am I missing something? I can't find anything in the release notes about this at least. – Darwind Dec 04 '17 at 07:24
  • 1
    It's done on the data binding side and it's in the works! – Jose Alcérreca Dec 05 '17 at 09:51
  • 1
    Hello.. can someone provide a link of sample that uses ViewModel with 2 way data binding as discussed above. Pleaseeee.... – iMDroid Dec 29 '17 at 13:26
  • Thanks extending ObservableViewModel class solves my problem awesome – Duran Jayson Jun 14 '18 at 07:23
7

Maybe this didn't exist when when the question was asked, but there is another option explained in this article: https://medium.com/google-developers/android-data-binding-observability-9de4ff3fe038

Basically instead of extending from BaseObservable you can implement android.databinding.Observable.

It's slightly more work as you need to also do the following:

  1. Create this variable in your model class

    private PropertyChangeRegistry registry = new PropertyChangeRegistry();
    
  2. Implement the overriden methods like this

    @Override
    public void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
        registry.add(callback);
    }
    
    @Override
    public void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
        registry.remove(callback);
    }
    
  3. Replace all the "BR" calls with these:

    registry.notifyChange(this, BR.bar);
    

Everything else works the same as extending from BaseObservable. So I think maybe this is the solution that Jose might have been alluding to which probably wasn't available back then. It seems to work.

Update: As Eugene Brusov has mentioned, you can now use LiveData with data binding. This is what I'm doing now and it's much easier with less boilerplate. See https://developer.android.com/topic/libraries/data-binding/architecture.

Michael Vescovo
  • 3,741
  • 4
  • 32
  • 45
4

It's possible with Android Studio 3.1 Canary 6 (https://androidstudio.googleblog.com/2017/12/android-studio-31-canary-6-is-now.html):

You can now use a LiveData object as an observable field in data binding expressions. The ViewDataBinding class now includes a new setLifecycle method that you need to use to use to observe LiveData objects.

You can find more details and sample in this Medium post.

Eugene Brusov
  • 17,146
  • 6
  • 52
  • 68
1

This can be also solved using a wrapper:

class SignInViewModelWrapper extends ViewModel {
    public final SignInViewModel model = new SignInViewModel();
}

class SignInViewModel extends BaseObservable {

    @Bindable
    public String getLogin() {
        return login;
    }

    @Bindable
    public String getPassword() {
        return password;
    }
}

You can then get the view model like this:

SignInViewModel signInViewModel = ViewModelProviders.of(this).get(SignInViewModelWrapper.class).model;