之前,我同时检查了问题this和this,但都没有解决我的问题。其次,我将详细解释所有内容,请原谅我的冗长文章。因此,我尝试首次在android中实现MVVM,并遵循了tuto1和tuto2的一些指南和步骤,正如我的问题所明确指出的那样,观察器中的on change方法未触发,我不明白为什么。这是我的代码架构:Authentication.java:@FormUrlEncoded@POST("service/api/login/")Call<LoginResponse> login(@Field("username") String username, @Field("password") String password);为了处理错误,我在tuto1之后实现了通用请求处理程序:GenericRequestHandler.java:public abstract class GenericRequestHandler<T extends Response> {private static final String TAG = GenericRequestHandler.class.getName();abstract protected Call<T> makeRequest();public final MutableLiveData<DataWrapper<T>> doRequest() { final MutableLiveData<DataWrapper<T>> liveData = new MutableLiveData<>(); final DataWrapper<T> dataWrapper = new DataWrapper<>(); makeRequest().enqueue(new ApiCallback<T>() { @Override protected void handleResponseData(T data) { Log.e(TAG, "handleResponseData: being handled"); dataWrapper.setData(data); liveData.postValue(dataWrapper); } @Override protected void handleError(String message) { Log.e(TAG, "handleError: error handled"); dataWrapper.setErrorMessage(message); liveData.postValue(dataWrapper); } @Override protected void handleException(Exception t) { Log.e(TAG, "handleException: exception handled"); dataWrapper.setApiException(t); liveData.postValue(dataWrapper); } @Override protected void handleHttpCodes(int code) { Log.e(TAG, "handleHttpCodes: code handled"); dataWrapper.setCode(code); liveData.postValue(dataWrapper); } }); return liveData;}}然后我从中制定了一个规范来处理登录:SignInRequestHandler.java:public class SignInRequestHandler extends GenericRequestHandler {private Authentication service = RestClient.getInstance().create(Authentication.class);private String username, password;public SignInRequestHandler(String username, String password) { this.username = username; this.password = password;}@Overrideprotected Call<LoginResponse> makeRequest() { return service.login(username, password);}public MutableLiveData<DataWrapper<LoginResponse>> onAuthRequest() { return doRequest();}}为了进行验证,我在模型中调用登录请求处理程序,如下所示:public MutableLiveData<DataWrapper<LoginResponse>> login() { SignInRequestHandler handler = new SignInRequestHandler(this.userName, this.pass); return handler.onAuthRequest();}这是viewModel:LoginVModel.java:public class LoginVModel extends ViewModel {private static final String TAG = LoginVModel.class.getName();private Driver driver; //this is my modelpublic MutableLiveData<String> username;public MutableLiveData<String> password;public MutableLiveData<DataWrapper<LoginResponse>> loginLiveData;public LoginVModel() { driver = new Driver(); username = new MutableLiveData<>(); loginLiveData = new MutableLiveData<>(); password = new MutableLiveData<>();}public void onLogin(View view) { Log.e(TAG, "onLogin: " + username.getValue() + " " + password.getValue() ); driver.setUserName(username.getValue()); driver.setPass(password.getValue()); loginLiveData = driver.login();}}为了更好地处理错误,我从tuto1实现了api观察器:ApiObserver.java:public class ApiObserver<T> implements Observer<DataWrapper<T>> {private ChangeListener<T> changeListener;public ApiObserver(ChangeListener<T> changeListener) { this.changeListener = changeListener;}@Overridepublic void onChanged(@Nullable DataWrapper<T> tDataWrapper) { if (tDataWrapper != null) if (tDataWrapper.getApiException() != null) changeListener.onFail(tDataWrapper.getApiException()); else if (tDataWrapper.getCode() != 0) changeListener.handleCodes(tDataWrapper.getCode()); else if (!tDataWrapper.getErrorMessage().equals("")) changeListener.onErrorMessage(tDataWrapper.getErrorMessage()); else changeListener.onSuccess(tDataWrapper.getData());}public interface ChangeListener<T> { void onSuccess(T dataWrapper); void onFail(Exception exception); void handleCodes(int code); void onErrorMessage(String message);}}在活动中,我对电子邮件和密码使用双向绑定,并且登录按钮从viewModel触发onLogin:SignInActivity.java:public class SignInActivity extends AppCompatActivity {private static final String TAG = SignInActivity.class.getName();private ActivitySignInBinding binding;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.activity_sign_in); Utilities.setHtmlText(R.string.forget_password, binding.forgetPassword); LoginVModel login = ViewModelProviders.of(this).get(LoginVModel.class); binding.setLoginModel(login); binding.setLifecycleOwner(this); login.loginLiveData.observe(this, new ApiObserver<>(listener));}private ApiObserver.ChangeListener<LoginResponse> listener = new ApiObserver.ChangeListener<LoginResponse>() { @Override public void onSuccess(LoginResponse dataWrapper) { startActivity(new Intent(getApplicationContext(), MainActivity.class)); finish(); } @Override public void onFail(Exception exception) { exception.printStackTrace(); CheckInternetConnection.requestFail(); } @Override public void handleCodes(int code) { // TODO: 10/2/2019 implement code handling here Log.e(TAG, "handleCodes: " + code); } @Override public void onErrorMessage(String message) { Log.e(TAG, "onErrorMessage: i'm here"); ToastMaker.getInstance().showErrorToast(message); }};}因此,我尝试使用错误的数据登录,从而触发错误消息,这是控制台日志:E/driver.itgds.khadametdz.viewmodel.viewmodel.LoginVModel: onLogin: test testE/driver.itgds.khadametdz.api.requesthandler.GenericRequestHandler: handleError: error handled所以不显示烤面包,上面的日志也不显示,所以请问我做错了什么?PS:对于通用处理程序中的实时数据,我同时尝试了.setValue()和.PostValue(),但它们均未获得理想的结果。编辑:我使用这种方法尝试了viewmodel,但是它什么也没有改变。 public void onLogin(View view) { Log.e(TAG, "onLogin: " + username.getValue() + " " + password.getValue() ); driver.setUserName(username.getValue()); driver.setPass(password.getValue());// loginLiveData = driver.login(); loginLiveData.postValue(driver.login().getValue());} 最佳答案 创建ViewModel时,您将像这样创建LiveDataloginLiveData = new MutableLiveData<>();因此,当您执行此操作时login.loginLiveData.observe(this, new ApiObserver<>(listener));您会收听此新的MutableLiveData ();。但是在用此替换LiveData的引用后loginLiveData = driver.login();因此,您不会观察到相同的MutableLiveData。我认为问题就在这里。
08-06 05:04