Ошибка наблюдателя MediatorLiveData для нескольких вызовов - PullRequest
0 голосов
/ 07 октября 2018
  • Я работаю над проектом, который загружает некоторые файлы при успешном входе в систему, а затем открывает Main Activity.Если это не так, он не регистрирует и не загружает файлы и предлагает пользователю успешно войти в систему для загрузки необходимых файлов.
  • После сбоя, если пользователь пишет правильное имя пользователя и пароль, он должен оба загружать файлыи откройте Основное действие.Однако в этом случае мое приложение вылетает.Если пользователь правильно пишет имя пользователя и пароль с первой попытки, приложение работает без проблем.

  • У меня есть 3 различных объекта LiveData, чтобы я мог наблюдать за всеми ними с помощью MediatorLiveDataи вызвать следующий в соответствии с условием.Вывод ошибки:

E / AndroidRuntime: FATAL EXCEPTION: main Процесс: com.cesar.sertificar, PID: 7482 java.lang.IllegalArgumentException: этот источник былуже добавлен с другим наблюдателем в android.arch.lifecycle.MediatorLiveData.addSource (MediatorLiveData.java:89) в com.cesar.sertificar.ui.activity.login.LoginViewModel.handleFirstRunProcess (LoginViewModel.java:101 в)com.cesar.sertificar.ui.activity.login.LoginActivity.doLogin (LoginActivity.java:68) на com.cesar.sertificar.ui.activity.login.LoginActivity.onClick (LoginActivity.java:88) на android.view.View.performClick (View.java:5214) на android.view.View $ PerformClick.run (View.java:20978) на android.os.Handler.handleCallback (Handler.java:739) на android.os.Handler.dispatchMessage(Handler.java:95) в android.os.Looper.loop (Looper.java:145) в android.app.ActivityThread.main (ActivityThread.java:6134) в java.lang.reflect.Method.invoke (собственный метод) на java.lang.reflect.Method.invoke (Яthod.java:372) на com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:1399) на com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1194)

LoginViewModel.class

void handleFirstRunProcess() {
        mIsNetworkAvailable.setValue(isAnActiveConnection());
        mProcessResult.addSource(mIsNetworkAvailable, isNetworkAvailable -> {
            mProcessResult.removeSource(mIsNetworkAvailable);
            if (isNetworkAvailable == null) return;

            if (!isNetworkAvailable) {
                mProcessResult.setValue(new NetworkState(NetworkState.Status.FAILED,
                        getApplication().getString(R.string.first_run_network_warning)));
                return;

            }

            doLogin(); //First doLogin
        });

        mProcessResult.addSource(mIsLoginSuccessful, isLoginSuccessful -> {
            mProcessResult.removeSource(mIsLoginSuccessful);
            if (isLoginSuccessful == null) return;

            if (isLoginSuccessful.getStatus() == NetworkState.Status.FAILED) {
                mProcessResult.setValue(new NetworkState(NetworkState.Status.FAILED,
                        getApplication().getString(R.string.login_error)));
                return;
            }

            if (preferenceUtil.getBooleanData(Constants.FIRST_RUN_KEY, true)) {
                downloadEmptyRecipientForm(); //Second download form if first run
            } else {
                mProcessResult.setValue(NetworkState.LOADED); //Open an activity
            }
        });

        mProcessResult.addSource(mIsFormDownloadingSuccessful, isFormDownloaded -> {
            mProcessResult.removeSource(mIsFormDownloadingSuccessful);
            if (isFormDownloaded == null) {
                return;
            }

            if (isFormDownloaded.getStatus() == NetworkState.Status.FAILED) {
                mProcessResult.setValue(new NetworkState(NetworkState.Status.FAILED,
                        getApplication().getString(R.string.first_run_empty_form_error)));
                return;
            }

            mProcessResult.setValue(NetworkState.LOADED); //Third open an activity
            preferenceUtil.putBooleanData(Constants.FIRST_RUN_KEY, false);
        });
    }

1 Ответ

0 голосов
/ 07 февраля 2019

Я столкнулся с той же проблемой в моей ViewModel.Похоже, что это внутреннее ограничение MediatorLiveData.Если он видит, что добавлен тот же тип LiveData, ему нужно, чтобы с ним работал тот же слушатель.Я просто добавлю свой случай, как это было с тем же типом ошибки и после (без ошибок, работает нормально).Код с ошибкой:

networkSum = new MediatorLiveData<>();
    networkSum.addSource(firstData, integer -> {
        if (integer == null) {
            firstIsFinished = false;
            errorInFirst = false;
        } else if (integer == SupportNetworkFunctions.STATUS_IN_PROGRESS) {
            networkSum.postValue(integer);
            firstIsFinished = false;
        } else if (integer == SupportNetworkFunctions.STATUS_FINISHED_WITH_ERROR) {
            firstIsFinished = true;
            errorInFirst = true;
            calculateFinished();
        } else {
            firstIsFinished = false;
            errorInFirst = false;
            calculateFinished();
        }
    });
    networkSum.addSource(secondData, integer -> {
        if (integer == null) {
            secondIsFinished = false;
            errorInSecond = false;
        } else if (integer == SupportNetworkFunctions.STATUS_IN_PROGRESS) {
            networkSum.postValue(integer);
            secondIsFinished = false;
        } else if (integer == SupportNetworkFunctions.STATUS_FINISHED_WITH_ERROR) {
            secondIsFinished = true;
            errorInSecond = true;
            calculateFinished();
        } else {
            secondIsFinished = false;
            errorInSecond = false;
            calculateFinished();
        }
    });

После рефакторинга:

networkSum = new MediatorLiveData<>();
    Observer<Integer> statusObserver = new Observer<Integer>() {
        @Override
        public void onChanged(@Nullable Integer integer) {
            if (integer != null) {

                if (integer == SupportNetworkFunctions.STATUS_IN_PROGRESS) {
                    networkSum.postValue(integer);
                } else if (integer == SupportNetworkFunctions.STATUS_FINISHED_WITH_ERROR) {
                    finishedItems++;
                    errorAppeared = true;
                    calculateFinished();
                } else {
                    finishedItems++;
                    calculateFinished();
                }
            }
        }
    };
    networkSum.addSource(firstData, statusObserver);
    networkSum.addSource(secondData, statusObserver);
...