#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 (или поток) Для представления, которое затем обновляется на основе этого.
Извините за мою Яву, в последнее время я немного оторвался от нее.