【问题标题】:Updating fields on change of another field in Android MVVM在 Android MVVM 中更改另一个字段时更新字段
【发布时间】:2020-06-05 21:05:00
【问题描述】:

我想实现,比如说温度单位转换器。我想使用 android MVVM 和数据绑定来做到这一点,但我不知道如何。 我有一个由三个 EditText 字段组成的片段:摄氏、华氏、开尔文。更改其中之一后,其余部分应自动更新。在没有数据绑定的情况下,我将 TextWatcher 设置为每个字段,并在 onTextChanged 中执行所有验证和转换逻辑并设置其他字段的值。在 beforeTextChanged 中,我删除了其他字段的侦听器,并在 afterTextChanged 中再次设置它们,以避免在一个字段更新时出现无限循环,触发 TextWatcher 更新另一个字段等等...

这是我如何在没有数据绑定的情况下实现这一目标的简化代码。

celsiusEditTextWatcher = new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        fahrenheitEditText.removeTextChangedListener(fahrenheitEditTextWatcher);
        kelvinEditText.removeTextChangedListener(kelvinEditTextWatcher);
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        double celsius = String.valueOf(celsiusEditText.getText());
        double fahrenheit = celsiusToFahrenheit(celsius);
        double kelvin = celsiusToKelvin(celsius)

        fahrenheitEditText.setText(Double.toString(fahrenheit));
        kelvinEditText.setText(Double.toString(kelvin));
    }

    @Override
    public void afterTextChanged(Editable s) {
        fahrenheitEditText.addTextChangedListener(fahrenheitEditTextWatcher);
        kelvinEditText.addTextChangedListener(kelvinEditTextWatcher);
    }
};

感谢任何帮助。

【问题讨论】:

  • 那么,你有什么问题?怎么回事?
  • 我想使用数据绑定来做同样的事情,拥有单独的 Fragment、ViewModel 和 Model 类。
  • 单独的片段是什么意思? 3 在 3 个片段上编辑文本?您能否将您的完整问题解释得更容易理解?
  • 你的问题是,你只是在说你想做什么,而不是what you actually want
  • 我想在用户编辑其中一个字段时更新其他字段(它们都在一个片段中,比如 ConverterFragment)。它与 textWatchers 一起使用,但现在我希望我的应用程序使用数据绑定和 MVVM,其中有 ConverterFragment、ConverterViewModel 和 TemperatureModel LiveData 和保持温度字段值的模型。问题是我不知道如何将数据绑定与 textWatchers 结合起来,或者除了 textWatcher 和数据绑定之外还有其他解决方案来实现该结果。

标签: android mvvm android-databinding


【解决方案1】:

我做了一个非常简单的解决方案。在这里,让 A 和 B 是当用户输入更改文本时需要同步的 EditText。同时它们对应的每一个 LiveData 都会更新:

活动

package marabillas.loremar.edittextmvvm;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;

import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;

public class MainActivity extends AppCompatActivity {

    private AViewModel viewModel;
    private AListener aListener = new AListener();
    private BListener bListener = new BListener();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final EditText a = findViewById(R.id.aEdit);
        final EditText b = findViewById(R.id.bEdit);

        viewModel =
                new ViewModelProvider(getViewModelStore(), new ViewModelProvider.NewInstanceFactory()).get(AViewModel.class);

        a.addTextChangedListener(aListener);
        b.addTextChangedListener(bListener);

        viewModel.isFieldsSynced = false;

        viewModel.aEditData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                if (!a.getText().toString().equals(s)) {
                    a.setText(s);
                }

                if (viewModel.isFieldsSynced) {
                    viewModel.isFieldsSynced = false;
                } else {
                    viewModel.isFieldsSynced = true;
                    b.setText("A changed");
                }
            }
        });

        viewModel.bEditData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                if (!b.getText().toString().equals(s)) {
                    b.setText(s);
                }

                if (viewModel.isFieldsSynced) {
                    viewModel.isFieldsSynced = false;
                } else {
                    viewModel.isFieldsSynced = true;
                    a.setText("B changed");
                }
            }
        });
    }

    class AListener implements TextWatcher {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

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

        @Override
        public void afterTextChanged(Editable s) {
            System.out.println("A text Changed");
            viewModel.aEditData.setValue(s.toString());
        }
    }

    class BListener implements TextWatcher {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

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

        }

        @Override
        public void afterTextChanged(Editable s) {
            System.out.println("B text changed");
            viewModel.bEditData.setValue(s.toString());
        }
    }
}

视图模型

package marabillas.loremar.edittextmvvm;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

public class AViewModel extends ViewModel {
    public boolean isFieldsSynced = false;
    public MutableLiveData<String> aEditData = new MutableLiveData<>();
    public MutableLiveData<String> bEditData = new MutableLiveData<>();
}

第一个if 逻辑是确定是否要更新A。第二个if 逻辑是确定是否要更新B。这里 A 是用户输入更改文本的 EditText。 B是EditText,它的文本需要和A同步。这对逻辑确保EditText和LiveData只更新一次。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-29
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多