java - 使用 ViewModel 仅在用户干预时调用

标签 java android mvvm observer-pattern

在我的 fragment 中,检查用户以查看他们的电子邮件是否在数据库中,然后转到注册或登录流程,我使用 ViewModel,此 View 模型使用电子邮件作为 MutableLiveData,这工作正常,但是当用户返回时,它会记住电子邮件已保存,然后立即与 API 对话,再次将其向前推。

使用什么方法等待用户调用?到目前为止,对于菜单而言,它可以在无需用户干预的情况下获取数据,并在更改时更改向用户显示的数据,这是正确的。但这是不同的。

我的(诚然很差) View 模型是:

public class ExistingUserViewModel extends ViewModel {
    private final MutableLiveData<String> email = new MutableLiveData<>();
    private final LiveData<ApiResponse<ExistingUserResponse>> existingUser;

    @Inject
    public ExistingUserViewModel(@NonNull ExistingUserRepository existingUserRepository){
        existingUser = Transformations.switchMap(email, input -> {
            if (input == null){
                return AbsentLiveData.create();
            }
            return existingUserRepository.isExistingUser(input);
        });
    }

    public LiveData<ApiResponse<ExistingUserResponse>> getIsExistingUser() { return existingUser; }

    @VisibleForTesting
    public void setEmail(String email1){
        email.setValue(email1);
    }
}

我的 fragment :

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    ((MainActivity) getActivity()).getSupportActionBar().hide();
    existingUserViewModel = ViewModelProviders.of(this, viewModelFactory).get(ExistingUserViewModel.class);
    existingUserListener();
}

private void refreshAndObserve() {
    existingUserViewModel.getIsExistingUser().observe(this, result -> {
        if (result.isSuccessful()) {
            try {
                String email = binding.get().emailEditText.getText().toString();
                if (result.body.getExists()) { // user exists
                    navigationController.navigateToLogin(email,null);
                } else {
                    navigationController.navigateToRegisterName(email);
                }
            } catch (NullPointerException e){
                Toast.makeText(getActivity(),e.toString(),Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(getActivity(),result.errorMessage,Toast.LENGTH_SHORT).show();
        }
    });
}

private void existingUserListener(){
    binding.get().continueButton.setOnClickListener(v -> submitDetails(v));
    binding.get().emailEditText.setOnKeyListener((v, keyCode, event) -> {
        if ((event.getAction() == KeyEvent.ACTION_DOWN)
                && (keyCode == KeyEvent.KEYCODE_ENTER)) {
            submitDetails(v);
            return true;
        }
        return false;
    });
}

private void submitDetails(View v) {
    refreshAndObserve();
    String email = binding.get().emailEditText.getText().toString();
    dismissKeyboard(v.getWindowToken());
    //todo: if valid do below
    existingUserViewModel.setEmail(email);
}

我已经考虑过何时进行观察,但不确定如何最好地处理此数据保留问题

最佳答案

我现在能想到的唯一方法就是将 boolean 值应用于submitDetails到isUserClicked,然后在onCreateView中将其设置为false,并在submitDetails中再次将其设置为true,然后将观察者更改为&& isUserClicked。对此解决方案不满意,但它至少会起作用。

还注意到我必须删除一个观察者,因为它堆叠到我的弹出堆栈上,因此解决了如果其他人感兴趣的话

            try {
                String email = binding.get().emailEditText.getText().toString();
                existingUserViewModel.getIsExistingUser().removeObservers(this);
                if (result.body.getExists()) { // user exists
                    navigationController.navigateToLogin(email, null);
                } else {
                    navigationController.navigateToRegisterName(email);
                }
            } catch (NullPointerException e) {
                Toast.makeText(getActivity(), e.toString(), Toast.LENGTH_SHORT).show();
            }

关于java - 使用 ViewModel 仅在用户干预时调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58205139/

相关文章:

java - 如果存在则使用值否则使用默认值 MySQL

java - 通过比较器对 ArrayList 进行排序

带参数的 Java 私有(private)构造函数

c# - 获取 WPF Treeview 的 SelectedItem

wpf - Wpf MVVM 中的数据绑定(bind)

java - Android 以什么形式返回 EXIF GPS 数据?

java - 我怎样才能在它自己的类中创建一个私有(private)方法以便反复使用

java - 将数据添加到数组列表

android - ActionbarSherlock 溢出菜单样式问题

wpf - 如何在 WPF/Silverlight 中设置页眉/行