Android: лучший способ использовать Viewmodel для кэширования переходных данных пользовательского интерфейса из EditText - PullRequest
0 голосов
/ 28 августа 2018

В моем приложении есть рабочий код, который кажется неуклюжим, и я хотел бы его оптимизировать. У меня есть форма с несколькими элементами управления EditText. Некоторые из них открывают другой фрагмент, где пользователь выбирает материал и возвращается к основному фрагменту. Связь осуществлялась через интерфейсы, данные в связках и основной фрагмент, который повторно использовался через oFragment = (MainFragment) getSupportFragmentManager().findFragmentByTag(MainFragmentTag);. Я использовал только модели представления для хранения и извлечения данных из баз данных. После того, как пользователь сделал свой выбор, я прочел текстовое содержимое элементов управления и сохранил его в новой записи POJO, которая была сохранена в базе данных.

Теперь я узнал об использовании Shared ViewModels для хранения временных данных и их распределения между фрагментами. Если вы можете выбирать элементы из списка, это действительно просто реализовать (из компонентов архитектуры Android):

public class SharedViewModel extends ViewModel {
    private final MutableLiveData<Item> selected = new MutableLiveData<Item>();

    public void select(Item item) {
        selected.setValue(item);
    }

    public LiveData<Item> getSelected() {
        return selected;
    }
}


public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends Fragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, item -> {
           // Update the UI.
        });
    }
}

Я думаю, что это можно использовать и для хранения данных TextEdit. Я бы чувствовал себя более комфортно, если бы данные пользовательского интерфейса хранились в моделях представления, вместо которых они читали пользовательские элементы управления во время процесса сохранения - из того, что я сейчас говорю о жизненных циклах Android, эти данные пользовательского интерфейса будут потеряны, если пользователь повернет экран. И я бы избавился от раздувного кода, чтобы использовать тот же экземпляр основного фрагмента.

Моя реализация использования Viewmodels для объединения данных EditText опубликована ниже и работает, но кажется довольно неуклюжей. Можете ли вы порекомендовать мне лучший способ сделать это? Или я сильно волнуюсь, и SavedInstanceState всегда будет хранить вещи, набранные пользователем в editTexts? Ниже мой код:

В основных фрагментах OnCreateView:

if (oStandardModel.getSelected().getValue() != null && !oStandardModel.getSelected().getValue().isEmpty()){
        oBinding.EditNumber.setText(oStandardModel.getSelected().getValue());
    }

    oBinding.EditNumber.addTextChangedListener(new Manager.TextValidator(oBinding.EditNumber) {
        @Override public void CacheIfValid(TextView textView, String text) {
            if (text != null && !text.isEmpty() && Manager.isNumeric(text)){
                oStandardModel.type(text.replaceAll(",", "."));
            }
        }
    });

CacheifValid вдохновлен классом, который я украл у здесь . Он был предназначен для проверки текста, но я злоупотребляю им для хранения введенных пользователем данных (класс в служебном классе, называемом «менеджер»):

public static abstract class TextValidator implements TextWatcher {
    private final TextView textView;

    public TextValidator(TextView textView) {
        this.textView = textView;
    }

    public abstract void CacheIfValid(TextView textView, String text);

    @Override
    final public void afterTextChanged(Editable s) {
        String text = textView.getText().toString();
        CacheIfValid(textView, text);
    }

    @Override
    final public void beforeTextChanged(CharSequence s, int start, int count, int after) { /* Don't care */ }

    @Override
    final public void onTextChanged(CharSequence s, int start, int before, int count) { /* Don't care */ }
}

Соответствующие поля в классе ViewModel выглядят так:

private final MutableLiveData<String> selected = new MutableLiveData<String>();

public void type(String item) {
    selected.setValue(item);
}

public MutableLiveData<String> getSelected() {
    return selected;
}

Спасибо за чтение!

...