viewModel 未返回更新的响应

viewModel not returning updated response

用户打开登录 activity。输入手机和错误的密码。一切顺利,敬酒显示 "Incorrect user/password."

现在在同一个 activity 中,用户输入 正确的 凭据。但它仍然祝酒显示 "Incorrect user/password." 但如果他回到任何其他 activity 并且回来一切正常。

这是我的代码片段。

存储库

public class LoginRepository {
    @Inject
    @Named("with_out_authorization")
    RestInterface restInterface;

    private static final String TAG = LoginRepository.class.getSimpleName();
    private static LoginRepository loginRepository;

    public LoginRepository() {
        AppController.getInstance().getNetComponent().inject(this);
    }

    public synchronized static LoginRepository getInstance() {
        //TODO No need to implement this singleton in Part #2 since Dagger will handle it ...
        if (loginRepository == null) {
            if (loginRepository == null) {
                loginRepository = new LoginRepository();
            }
        }
        return loginRepository;
    }

    public LiveData<LoginResponse> tryLogin(String mobileNumber, String password) {
        final MutableLiveData<LoginResponse> data = new MutableLiveData<>();
        Call<LoginResponse> call = restInterface.Login(mobileNumber, password);
        call.enqueue(new Callback<LoginResponse>() {
            @Override
            public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {
                Log.d(TAG, "onResponse response:: " + response);
                if (response.body() != null) {
                    data.setValue(response.body());
                }
                else{
                    data.setValue(null);
                }
            }

            @Override
            public void onFailure(Call<LoginResponse> call, Throwable t) {
                data.setValue(null);
            }
        });

        return data;
    }
}

查看模型

public class LoginViewModel extends AndroidViewModel {

    private final LiveData<LoginResponse> loginResponseObservable;
    private static final String TAG = "LoginViewModel";

    public LoginViewModel(Application application, final String mobileNumber, final String password) {
        super(application);

        // If any transformation is needed, this can be simply done by Transformations class ...
        loginResponseObservable = LoginRepository.getInstance().tryLogin(mobileNumber, password);
        Log.e(TAG, loginResponseObservable.toString());
    }

    /**
     * Expose the LiveData so the UI can observe it.
     * */
    public LiveData<LoginResponse> getLoginResponseObservable() {
        return loginResponseObservable;
    }

    public static class Factory extends ViewModelProvider.NewInstanceFactory {
        @NonNull
        private final Application application;
        private final String mobileNumber;
        private final String password;

        public Factory(@NonNull Application application, String mobileNumber, String password) {
            this.application = application;
            this.mobileNumber = mobileNumber;
            this.password = password;
        }

        @Override
        public <T extends ViewModel> T create(Class<T> modelClass) {
            //noinspection unchecked
            return (T) new LoginViewModel(application, mobileNumber, password);
       }
    }
}

Activity

public void btnLoginClicked(View v) {

    if (!validateForm() || !isConnected())
        return;

    String mobileNumber = editTextMobile.getText().toString();
    String password = editTextPassword.getText().toString();

    LoginViewModel.Factory factory = new LoginViewModel.Factory(getApplication(),
            mobileNumber, password);

    final LoginViewModel viewModel =
            ViewModelProviders.of(this, factory).get(LoginViewModel.class);
    observeLoginViewModel(viewModel);
}

private void observeLoginViewModel(LoginViewModel viewModel) {
    // Update the list when the data changes
    viewModel.getLoginResponseObservable().observe(this, new Observer<LoginResponse>() {
        @Override
        public void onChanged(@Nullable LoginResponse loginResponse) {
            Utility.displayToast(loginResponse.getMessage());
            if (loginResponse.getCode() == HttpStatus.LOGIN_SUCCESSFUL) {
                updatePreferences(loginResponse);
                Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                startActivity(intent);
                finish();
            }
        }
    });
}

这个实现有什么不正确的地方?请帮忙。

我认为问题是你把你的代码:

loginResponseObservable = LoginRepository.getInstance().tryLogin(mobileNumber, password);

在您的 ViewModel 构造函数中。但是正如您所见,此构造函数仅被调用一次,首先尝试在 activity:

中获取 viewModel 实例
final LoginViewModel viewModel =
        ViewModelProviders.of(this, factory).get(LoginViewModel.class)

在下次尝试时(例如,在第二次单击 Button 之后),您将获得相同的 ViewModel 实例(比方说,这里的 ViewModelProviders 有点像 HashMap,LoginViewModel.class - 是 [=26 的关键=] 需要 ViewModel。因此,首先尝试此 HashMap 不包含您的 ViewModel,这就是调用构造函数的原因,所有接下来的尝试都会 return 现有的 ViewModel)。这里的工厂 - 只是一种将参数放入 ViewModel 的构造函数的方法,但它不能保证 ViewModel 会被重新创建。

所以你可以删除你的代码

loginResponseObservable = LoginRepository.getInstance().tryLogin(mobileNumber, password);

进入另一个 ViewModel 的 public 方法并在每次单击 Button 后调用它