Обновление полей при смене другого поля в Android MVVM - PullRequest
0 голосов
/ 21 февраля 2020

Я хочу реализовать, скажем, преобразователь температуры. Я хочу сделать это, используя android MVVM и привязку данных, но я не знаю, как. У меня есть фрагмент, который состоит из трех полей EditText: Цельсий, Фаренгейт, Кельвин. После изменения одного из них, остальные должны автоматически обновляться. Без привязки данных я устанавливаю TextWatcher для каждого поля, а в onTextChanged я делаю все логи проверки и преобразования c и устанавливаю значение для других полей. В beforeTextChanged я удалял слушателей для других полей, а в afterTextChanged устанавливал их снова, чтобы избежать бесконечного l oop при обновлении одного поля, запускает 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 Ответ

0 голосов
/ 21 февраля 2020

Я сделал очень простое решение. Здесь, пусть A и B являются EditTexts, которые должны синхронизироваться c, когда текст изменяется пользователем. В то же время обновляются все соответствующие им LiveData:

Activity

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

ViewModel

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 logi c предназначен для определения если А должен быть обновлен. Второй if logi c предназначен для определения необходимости обновления B. Здесь A - EditText, текст которого изменяется при вводе пользователем. B - это EditText, текст которого должен синхронизироваться c с A. Эта пара логик c гарантирует, что EditText и LiveData обновляются только один раз.

...