прежде всего, я проверил оба вопроса это и это , ни один из них не решил мою проблему.
во-вторых, я объясню все подробно,прошу прощения за длинный пост.
, поэтому я впервые пытаюсь внедрить MVVM в android и следую некоторым инструкциям и шагам из tuto1 и tuto2, как выяснилось в моем вопросе, включенный метод в наблюдателе не срабатывает, и я не могу понять, почему. Вот моя архитектура кода:
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;
}
@Override
protected 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 model
public 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();
}
}
для лучшей обработки ошибок, я реализовал API-обозреватель из tuto1:
ApiObserver.java:
public class ApiObserver<T> implements Observer<DataWrapper<T>> {
private ChangeListener<T> changeListener;
public ApiObserver(ChangeListener<T> changeListener) {
this.changeListener = changeListener;
}
@Override
public 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);
}
}
в упражнении, я использую двустороннюю привязку для электронной почты и пароля, а кнопка входа вызывает onLogin из viewModel:
SignInActivity.java:
public class SignInActivity extends AppCompatActivity {
private static final String TAG = SignInActivity.class.getName();
private ActivitySignInBinding binding;
@Override
protected 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 test
E/driver.itgds.khadametdz.api.requesthandler.GenericRequestHandler: handleError: error handled
, чтобы тост не отображался, а также журнал над ним, так что, пожалуйста, что я сделал не так?
PS: для живых данных в универсальном обработчике я пробовал оба.setValue () и .PostValue (), ни один из них не получает желаемого результата.
Редактировать: Я пытался использовать модель представления с помощью этого метода, и она ничего не изменила.
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());
}