Конфликт с EditText: Watcher для View + Observer для MutableLiveData - PullRequest
0 голосов
/ 23 января 2020

У меня возникают проблемы с пониманием того, как парадигма Fragment + ViewModel работает с View как EditText .

Будучи EditText, он, очевидно, будет изменен в представлении (фрагмент). Но я также хочу иметь возможность изменить его в ViewModel: например, чтобы стереть его текст.

Вот код в классе Fragment:

public void onActivityCreated(@Nullable Bundle savedInstanceState) {
...
        comment = mViewModel.getComment();
        comment.observe(getViewLifecycleOwner(), new Observer<String>() {
            @Override
            public void onChanged(String s) {
                commentView.setText(s);
            }
        });
...
        commentView.addTextChangedListener(new TextWatcher() {
            @Override
            public void afterTextChanged(Editable s) {
                mViewModel.setComment(String.valueOf(s));
            }
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) { }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) { }
        });

Как видите, я установил наблюдатель , поэтому, когда я изменяю значение MutableLiveData, представление изменяется. И я установил watcher , поэтому, когда я (при использовании приложения) изменяю значение View, MutableLiveData изменяется.

Вот код класса ModelView:

public void addRegister() {
...
String comment = this.comment.getValue();
...
this.comment.setValue("");

Когда я запускаю приложение, не появляется сообщение об ошибке, но оно зависает. Я думаю, из-за бесконечного l oop. Как мне подходить к EditTexts с этой парадигмой View + ViewModel? Что я не понимаю?

Большое спасибо заранее!

Ответы [ 2 ]

0 голосов
/ 30 января 2020

в вашем обозревателе для комментариев liveData, просто сначала отмените регистрацию TextWatcher, затем после setText из комментария liveData перерегистрируйте TextWatcher, все должно быть в порядке:)

0 голосов
/ 23 января 2020

Для этого можно использовать двустороннюю привязку данных:

  • Когда пользователь вводит текст: текущие данные будут обновляться
  • Если вы установите значение данных в реальном времени программно, Содержимое EditText будет обновлено

Вы сможете удалить обоих слушателей в своей деятельности, поскольку привязка данных сделает это за вас.

build.gradle:

android {
    dataBinding {
        enabled = true
    }
}

layout:

  • добавить элемент <layout> на верхнем уровне
  • определить переменную для вашей модели представления
  • подключить EditText к представлению модель
<layout>
    <data>
        <variable
            name="viewModel"
            type="com.mycompany.AddRegisterViewModel" />
    </data>
    <EditText
                android:id="..."
                android:layout_width="..."
                android:layout_height="..."
                android:text="@={viewModel.getComment()}" />
</layout>

Фрагмент (извините, kotlin пример):

  • Подсоедините поле viewModel в xml к объекту viewmodel:
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val binding: MyFragmentBinding = DataBindingUtil.inflate(inflater, R.layout.my_fragment, container, false)
        binding.setViewModel(myViewModel)

Обратите внимание, что вам нужен знак равенства, @=, чтобы иметь двустороннюю привязку данных. Если вы просто используете @{viewModel.getComment()}, то текст для редактирования будет обновлен, если вы программно установите значение данных в реальном времени, но другой способ не будет работать.

Примечания:

  • Вы можете использовать ObservableField вместо MutableLiveData для привязки данных, если вы предпочитаете
  • Возможно, вы можете ссылаться на текущие данные в xml со ссылкой на поле вместо ссылки на метод, такой как @={viewModel.comment}

Справка: Android документация для двусторонней привязки данных: https://developer.android.com/topic/libraries/data-binding/two-way

...