Search code examples
androidandroid-databinding2-way-object-databinding

2-way databinding with ObservableField<>, set() doesn't work?


I have a parent class, lets call it BaseViewModel, this class can be typed and have an ObservableField of the same type. Like this :

public class BaseViewModel<T> extends BaseObservable {

    ObservableField<T> value = new ObservableField<>();

    public T getValue() {
        return value.get();
    }

    public void setValue(T value) {
        this.value.set(value);
        setHasChanges(value != originalValue);
    }

}

I got many child for this class. One of them is StringViewModel that, like its name says, gives a String value. This child class overrides the setValue() method :

public class StringViewModel extends BaseViewModel<String> {

    @Override
    public void setValue(String value) {
        this.value.set(value);
        if(value != null && !value.isEmpty()){
            setHasChanges(!value.equals(originalValue));
        }
        else if(originalValue == null)
            setHasChanges(false);
        else
            setHasChanges(!originalValue.isEmpty());
    }

    //Other methods ...

}

And I got a layout that use a StringViewModel :

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="viewModel"
            type="com.myproject.viewmodels.StringViewModel" />

    </data>

    <EditText
        android:id="@+id/value"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"

        android:clickable="@{viewModel.editable}"
        android:cursorVisible="@{viewModel.editable}"

        android:ellipsize="end"
        android:focusable="@{viewModel.editable}"
        android:focusableInTouchMode="@{viewModel.editable}"
        android:inputType="textMultiLine|textNoSuggestions"

        android:text="@={viewModel.value}"
        app:setError="@{viewModel.error}"

        tools:text="Dupont" />

    <!-- Other layouts ... -->

But when I call the setValue() method of my StringViewModel, the value is set to the ViewModel but not on the EditText.

Edit : I should also say that I've add my StringViewModel to my DataBinding correctly (using DataBindingUtil to inflate my DataBinding).

myDataBinding.setViewModel(new StringViewModel());

Does someone got an explanation to this behavior?


EDIT

As @iMDroid said, I should have call notifyChange() in my method setValue(). I tought ObservableFields was doing it for me, my bad.


Solution

  • I am not expert in two-way data binding.. but I have been reading articles about it so here is one solution which might help you.

    Suppose your model class is this:

    public class Echo {
      public String text;
    }
    

    And your layout file is R.layout.echo

    They say you are supposed to set the layout using the DataBindingUtil class and then the object on which you make the binding that is EchoBinding (automatically generated according to the layout) like this:

     EchoBinding binding = DataBindingUtil.setContentView(
          this, R.layout.echo);
        binding.setEcho(new Echo());
    

    Also, you can bind the value to your EditText using app:binding="@{echo.text}" attribute.

    <EditText
      android:layout_width=”match_parent”
      android:layout_height=”wrap_content”
      android:hint="Text 1"
      app:binding="@{echo.text}"/>
    

    And lastly add notifyChange() to your setValue() method.

    Refer to this link for more information.

    You may give it a try.. Hope it helps.