Как реализовать архитектуру MVVM при использовании TextView для отображения значения панели поиска после его изменения в результате взаимодействия с пользователем?

#java #android #mvvm

Вопрос:

Прямо сейчас у меня есть панель поиска, к которой прикреплен onseekbarchangelistener, который изменяет значение TextView(целевая температура) каждый раз, когда панель поиска перемещается.

         @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
         Log.d(TAG, "onProgressChanged: progress: "   progress);
            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O) {
                float addTo18 = ((float)progress) / 2;
                Log.d(TAG, "onProgressChanged: addTo18 "   addTo18);
                if(MainActivity.selectedThermostat.getValue().getIsCelsius())
                    targetTemperature.setText(Float.toString((float) (18.0   addTo18))); //u2109 for farenheit
                else
                    targetTemperature.setText(Float.toString((float) (64.0   addTo18))); //u2109 for farenheit
            } else {
                if(MainActivity.selectedThermostat.getValue().getIsCelsius()) {
                    float addTo18 = (float) ((float) progress - 18.0) / 2;
                    Log.d(TAG, "onProgressChanged: addTo18 "   addTo18);
                    targetTemperature.setText(String.valueOf(18.0   addTo18)); //u2109 for farenheit
                } else {
                    float addTo18 = (float) ((float) progress - 64.0) / 2;
                    Log.d(TAG, "onProgressChanged: addTo18 "   addTo18);
                    targetTemperature.setText(String.valueOf(64.0   addTo18)); //u2109 for farenheit
                }
            }
        }

 

Прочитав несколько статей о MVVM, я увидел, что изменения в представлениях(текстовые представления, изображения и т. Д.) В деятельности происходят в результате наблюдения за изменениями изменяемых объектов живых данных в модели представления.

В этом случае было бы лучше создать изменяемый объект данных в режиме реального времени в viewmodel и внести в него изменения вместо непосредственного внесения изменений в TextView(targetTemperature).

По существу

Взаимодействие с пользователем -> изменение панели поиска ->> Изменение текстового представления

или

Взаимодействие с пользователем -> изменение панели поиска ->> изменение изменяемых данных в режиме реального времени в модели представления ->>> изменение текстового представления

Ответ №1:

Вы можете сделать следующее:

ваш класс ViewModel выглядит следующим образом:

 public class SeekViewModel extends ViewModel {

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

    public void onSeekBarChanged(SeekBar seekBar, int progress, boolean fromUser) {
        text.set("Your progress: "   progress);
    }
}
 

ваш файл xml-макета:

 <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        tools:context=".MainActivity">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{viewModel.text}"
            />

        <androidx.appcompat.widget.AppCompatSeekBar
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onProgressChanged="@{viewModel.onSeekBarChanged}"
            android:max="10"
            android:progress="1"
            />
</LinearLayout>
 

В вашем классе занятий сделайте вот так:

 mActivityBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        viewModel = new ViewModelProvider(this).get(SeekViewModel.class);
        mActivityBinding.setViewModel(viewModel);
 

Ответ №2:

Если это всего лишь изменение пользовательского интерфейса, то прямое изменение текстового представления нормально.

Однако обычно, когда пользователь вводит что-то, вы захотите использовать это где-то еще, кроме самого пользовательского интерфейса, поэтому безопасный способ-второй.

За исключением того, что я бы не стал раскрывать изменяемые данные из ViewModel, вместо этого у меня есть метод, похожий на onTemperatureChanges(значение: Int), и ViewModel выполняет вычисления, имеет частные изменяемые данные и предоставляет живые данные через геттер.

Таким образом, это выглядело бы примерно так: Просмотр

 viewModel.getTemperature().observe(lifecycleObserver, new Observer<String>() {
  @Override
  void onChanged(String text) {
    targetTemperature.setText(text)
  }
);

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
  Log.d(TAG, "onProgressChanged: progress: "   progress);
  viewModel.onTemperatureChanges(progress)
}
 

Модель представления:

 private MutableLiveData<String> temperature;

LiveData<String> getTemperature() {
  return temperature;
}

void onTemperatureChanges(int progress) {
  // not really sure why you depend on os version or if this calculation is correct, so I just add one section of it
  if (true == isCelsius.getValue()) { // isCelsius another livedata, which you update based on the UI
    temperature.setValue(String.valueOf(((float) progress - 18.0) / 2   18.0));
  } else {
    temperature.setValue(String.valueOf(((float) progress - 64.0) / 2   64.0));
  }
}
 

Основная идея заключается в том, что представление (Действие или фрагмент и т. Д.) Должно Просто делегировать свои пользовательские данные модели представления, а модель представления должна выполнять вычисления, изменения данных и т. Д., А затем предоставлять состояние через livedata (или поток) Для представления, которое затем обновляется на основе этого.

Извините за мою Яву, в последнее время я немного оторвался от нее.