Наблюдение за изменением данных в реальном времени не происходит при изменении - PullRequest
0 голосов
/ 03 октября 2019

прежде всего, я проверил оба вопроса это и это , ни один из них не решил мою проблему.

во-вторых, я объясню все подробно,прошу прощения за длинный пост.

, поэтому я впервые пытаюсь внедрить 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());
}

1 Ответ

0 голосов
/ 03 октября 2019

Когда вы создаете вашу ViewModel, вы создаете LiveData, как это

loginLiveData = new MutableLiveData<>();

Таким образом, когда вы делаете это

login.loginLiveData.observe(this, new ApiObserver<>(listener));

, вы слушаете эту новую MutableLiveData <> () ;. Но после того, как вы замените ссылку LiveData этим

loginLiveData = driver.login();

, значит, вы не наблюдаете тот же MutableLiveData. Я думаю, что проблема здесь.

...