【问题标题】:How to implement MVVM architecture when using TextView to display Seekbar value after it is changed by user interaction?用户交互更改后使用TextView显示Seekbar值时如何实现MVVM架构?
【发布时间】:2021-07-30 02:42:34
【问题描述】:

现在我有一个搜索栏,它附加了一个 onseekbarchangelistener,每次搜索栏移动时都会更改 TextView(targetTemperature) 的值。

        @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 的文章后,我看到活动中视图(TextViews、ImageViews 等)的变化来自于观察视图模型中可变实时数据对象的变化。

在这种情况下,最好在视图模型中创建一个可变的实时数据对象并对其进行更改,而不是直接更改 TextView(targetTemperature)。

基本上

用户交互 -> 搜索栏改变 -> textView 改变

用户交互 -> 搜索栏更改 -> 更改视图模型中的可变实时数据 -> 文本视图更改

【问题讨论】:

    标签: java android mvvm


    【解决方案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>
    

    在你的 Activity 类中这样做:

    mActivityBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    
            viewModel = new ViewModelProvider(this).get(SeekViewModel.class);
            mActivityBinding.setViewModel(viewModel);
    

    【讨论】:

      【解决方案2】:

      如果只是改变UI,直接修改textView就可以了。

      但是,通常当用户输入某些内容时,您会想在 UI 本身以外的其他地方使用它,所以安全的方法是第二种。

      除了,我不会从 ViewModel 公开 MutableLiveData,而是使用类似 onTemperatureChanges(value: Int) 的方法,ViewModel 进行计算,拥有私有的 MutableLiveData 并通过 getter 公开 LiveData。

      所以它看起来像这样: 查看

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

      基本思想是视图(Activity 或 Fragment 等)应该只将其用户输入委托给 ViewModel,而 ViewModel 应该进行计算、数据修改等,然后通过 livedata(或流)向视图公开状态然后根据它进行更新。

      对不起我的Java,我最近有点脱节了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-05
        • 1970-01-01
        相关资源
        最近更新 更多