Ad

ObservableField Value Inside ViewModel Does Not Update UI With Data Binding

ObservableField<Marker> value inside ViewModel class value is changed using EditText in layout however value is not propagated to TextView tv_summary.

This is the layout

<?xml version="1.0" encoding="utf-8"?>

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

    <data>
        <import type="com.example.tutorial5livedata_mvvm_room_recyclerview.util.BindingUtils"/>
        <variable
            name="viewModel"
            type="com.example.tutorial5livedata_mvvm_room_recyclerview.viewmodel.AddMarkerViewModel"/>

    </data>

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="Title"
            android:textColor="#FC7100"
            android:textSize="18sp"
            android:textStyle="bold"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toTopOf="parent" />

        <EditText
            android:id="@+id/et_title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_marginTop="8dp"
            android:ems="10"
            android:hint="Title"
            android:inputType="textPersonName"
            android:text="@={viewModel.markerObservableField.title}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toBottomOf="@+id/tv_title" />


        <TextView
            android:id="@+id/tv_latitude"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="Latitude"
            android:textColor="#FC7100"
            android:textSize="18sp"
            android:textStyle="bold"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toBottomOf="@+id/et_title" />

        <EditText
            android:id="@+id/et_latitude"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="8dp"
            android:layout_marginTop="8dp"
            android:ems="10"
            android:hint="Latitude"
            android:text="@={viewModel.markerObservableField.latitude}"
            android:inputType="number"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toBottomOf="@+id/tv_latitude" />



        <TextView
            android:id="@+id/tv_summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:text='@{viewModel.markerObservableField.title + " " + viewModel.markerObservableField.latitude}'
            app:layout_constraintStart_toStartOf="@+id/guideline_left"
            app:layout_constraintTop_toBottomOf="@+id/et_latitude" />


        <android.support.constraint.Guideline
            android:id="@+id/guideline_left"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_begin="8dp" />
    </android.support.constraint.ConstraintLayout>
</layout>

ViewModel class

public class AddMarkerViewModel extends AndroidViewModel {

    private MarkerRepository mMarkerRepository;
    public ObservableField<Marker> markerObservableField = new ObservableField<>();


    public AddMarkerViewModel(@NonNull Application application) {
        super(application);

        AppDatabase appDatabase = AppDatabase.getInstance(application.getApplicationContext());

        mMarkerRepository = MarkerRepository
                .getsInstance(MarkerLocalDataSource.getInstance(appDatabase.markerDao(), new AppExecutors()));
        if (markerObservableField.get() == null) {
            Marker marker = new Marker();
            marker.setTitle("New Title");
            markerObservableField.set(marker);
        }
    }


    public long addMarker(Marker marker) {
        return mMarkerRepository.addMarker(marker);
    }
}

onCreate method of Activity for adding marker to set values

   protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_add_marker);
        mAddMarkerViewModel = ViewModelProviders.of(this).get(AddMarkerViewModel.class);
        mBinding.setViewModel(mAddMarkerViewModel);

    }
Ad

Answer

In order to listen to property changes, you will need to extend BaseObservable.

I think the problem here is that property change does not fire event, because you listen to Field change, that is marker object itself, that stays same.

Marker field Latitude is not observable, that means it's impossible to detect it's change.

You have two options.

If you want to detect changes, you can create observable field for Latitude.

public ObservableField<String> latitudeObservableField = new ObservableField<>();

You can listen to field Changes and update marker object.

 latitudeObservableField.addOnPropertyChangedCallback(() -> {
 // Update marker object
})

Another approach would be to make Marker extend BaseObservable, like explained in attached reference.

Please check out official documentation on observable objects.

Ad
source: stackoverflow.com
Ad