当前位置: 首页 > 知识库问答 >
问题:

在Android MVVM 中更改另一个字段时更新字段

司徒英卓
2023-03-14

我想实现,让我们说温度单位转换器。我想使用AndroidMVVM和数据绑定来做到这一点,但我不知道如何。我有一个片段,它由三个编辑文本字段组成:摄氏度,华氏度,开尔文。更改其中之一后,其余部分应自动更新。在没有数据绑定的情况下,我将 TextWatcher 设置为每个字段,并在 onTextChanged 中执行所有验证和转换逻辑,并设置其他字段的值。在之前文本更改中,我删除了其他字段的侦听器,并且在文本更改之后再次设置它们,以避免在一个字段更新时无限循环,触发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);
    }
};

感谢任何帮助。

共有1个答案

洪胤
2023-03-14

我做了一个非常简单的解决方案。这里,假设A和B是编辑文本,当用户输入的文本改变时,它们需要同步。与此同时,它们各自对应的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只更新一次。

 类似资料:
  • 我有两个实体具有@OneTomany(Entity1)&@ManyToOne(Entity2)双向关系。在@OneTomany关系中,我有@Cascading{Cascade.All}。但是当我在事务或方法中将具有@ManyToOne关系的实体的初始为false的boolean属性更改为true,然后又变回false时,它会导致数据库触发更新查询,将实体的boolean设置为false,这似乎是错

  • 假设我有两个字段F1和f2。我想将F1更新为。我可以在Mongo中使用一个更新命令吗?

  • 我正在使用Android MVVM架构和LiveData。我有一个这样的物体 我的视图模型是这样的 如何确保用户对象中的某个字段发生更改时,观察员收到通知?顺便说一句,重要的是要将这些数据保存在单独的对象中,而不是在ViewModel中使用字符串等主要值。

  • 问题内容: 您能否提供一个非常简单的SQL示例,说明如何创建一个“计数”或“订单”字段,该字段将自动递增,但在不同字段中进行每次更改后重新启动?在下表中,每次“进餐”(Meal)字段发生更改时,“订单”(Order)字段将从“ 1”重新开始。谢谢。 吃饭时间点餐 午餐10:30 午餐11:00引用2 午餐11:15 3 晚餐4:30 晚餐1晚餐4:45 晚餐2晚餐引用3 晚餐5:30引用4 问题答

  • 我正在尝试用Angular构建一个简单的计算器,如果我想的话,我可以覆盖总数。我有这部分的工作,但当我回去输入一个数字在一个或两个领域的总数没有在该领域的更新。 这是我的jsfiddlehttp://jsfiddle.net/YUza7/2/ 形式 javascript

  • 问题内容: 请注意:我 在 问我想回答的问题。我知道这个问题意味着数据库设置不佳。因此,我将否决所有建议更改表设置方式的答案。 我需要在更改一个值的同时复制一堆行。 需要成为: IE浏览器在这个表中的所有条目时,在表中创建一个新条目,其中和是复制的,并且是。 问题答案: 使用: 假设或列都不是主键,或者对两者都不具有唯一约束。