Android:使用Viewmodel从EditText缓存瞬态UI数据的最佳方法

时间:2018-08-27 21:43:58

标签: android observer-pattern android-viewmodel

在我的应用中,我有一个工作代码感觉笨拙,我想对其进行优化。我有一个带有几个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数据。将UI数据存储在视图模型中而不是在保存过程中读取用户控件时,我会感到更加自在-从我现在关于android生命周期的角度来看,如果用户旋转屏幕,则这些UI数据将会丢失。而且我将摆脱繁琐的代码来重用同一主片段实例。

我使用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受我从here窃取的类的启发。它用于文本验证,但是我滥用了它来存储用户输入的数据(实用程序类中的类“ manager”):

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

谢谢您的阅读!

0 个答案:

没有答案