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 后调用它
用户打开登录 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 后调用它