Значение ObservableField внутри ViewModel не обновляет пользовательский интерфейс с привязкой данных

Значение ObservableField<Marker> внутри значения класса ViewModel изменяется с помощью EditText в макете, однако значение не распространяется на TextView tv_summary.

это макет

<?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

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 метод Activity для добавления маркера к заданным значениям

   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);

    }

person Thracian    schedule 02.07.2018    source источник


Ответы (1)


Чтобы прослушивать изменения свойств, вам потребуется расширить BaseObservable.

Я думаю, что проблема здесь в том, что изменение свойства не вызывает событие, потому что вы слушаете изменение поля, то есть сам объект маркера, который остается прежним.

Marker поле Latitude не просматривается, то есть невозможно обнаружить его изменение.

У вас есть два варианта.

Если вы хотите обнаружить изменения, вы можете создать наблюдаемое поле для Latitude.

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

Вы можете прослушивать изменения поля и обновлять объект маркера.

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

Другой подход состоит в том, чтобы сделать Marker расширением BaseObservable, как описано в прилагаемой ссылке.

Ознакомьтесь с официальной документацией по наблюдаемым объектам.

person Ioane Sharvadze    schedule 02.07.2018
comment
Возможно, ты прав. Я просто меняю свойства маркера, это должно быть причиной того, что он не обновляет пользовательский интерфейс. Я уже использую Marker с LiveData‹List‹Marker›› в другом действии, расширение BaseObservable сделает его более тяжелым в памяти, особенно я использую его со списком. Я думаю, что добавлю String и Integer ObservableFields в ViewModel, чтобы отправлять изменения в пользовательский интерфейс, но создавать по одному для каждого свойства громоздко. Я искал менее закодированное решение. - person Thracian; 02.07.2018
comment
Значит, ObservableField‹Object› бесполезен при привязке данных? - person Thracian; 02.07.2018
comment
Насколько я понимаю, если вы используете ObservableField , он хорошо работает с примитивными типами, поскольку они неизменяемы, и вам придется обновлять ObservableField напрямую. Для использования объектов я не думаю, что есть способ обнаружить изменение объекта. Для этого вам придется вручную уведомлять об изменениях полей. - person Ioane Sharvadze; 02.07.2018