viewModel не возвращает обновленный ответ - PullRequest
0 голосов
/ 28 апреля 2020

Пользователь открывает активность входа. Введите номер мобильного и неверный пароль. Все идет хорошо, и тосты показывают «Неверный пользователь / пароль».

Теперь в том же упражнении пользователь вводит правильные учетные данные. Но это все еще показывает, что «Неверный пользователь / пароль». Но если он возвращается к какой-либо другой деятельности и возвращается, все работает хорошо.

Это мой фрагмент кода.

Репозиторий

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);
       }
    }
}

Активность

publi c 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();
            }
        }
    });
}

Что не правильно в этой реализации? Пожалуйста, помогите.

1 Ответ

2 голосов
/ 28 апреля 2020

Мне кажется, проблема в том, что вы поместили свой код:

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

в конструктор ViewModel. Но, как вы можете видеть, этот конструктор вызывается только один раз, при первой попытке получить экземпляр viewModel в вашей деятельности:

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

При следующих попытках (например, после второго нажатия кнопки) вы получите тот же экземпляр ViewModel (допустим, что ViewModelProviders здесь является своего рода HashMap, а LoginViewModel.class - это ключ для возврата необходимого ViewModel. Поэтому с первой попытки этот HashMap не содержит вашу ViewModel, поэтому вызывается конструктор, все последующие попытки вернет существующую ViewModel). Фабрика здесь - это просто способ поместить аргументы в конструктор ViewModel, но это не гарантия того, что ViewModel будет воссоздан.

Так что вы можете удалить свой код

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

в какой-то другой ViewModel метод publi c и вызывайте его каждый раз после нажатия кнопки

...