nuhkoca
nuhkoca

Reputation: 1943

MediatorLiveData observer error for multiple calls

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.cesar.sertificar, PID: 7482 java.lang.IllegalArgumentException: This source was already added with the different observer at android.arch.lifecycle.MediatorLiveData.addSource(MediatorLiveData.java:89) at com.cesar.sertificar.ui.activity.login.LoginViewModel.handleFirstRunProcess(LoginViewModel.java:101) at com.cesar.sertificar.ui.activity.login.LoginActivity.doLogin(LoginActivity.java:68) at com.cesar.sertificar.ui.activity.login.LoginActivity.onClick(LoginActivity.java:88) at android.view.View.performClick(View.java:5214) at android.view.View$PerformClick.run(View.java:20978) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:145) at android.app.ActivityThread.main(ActivityThread.java:6134) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) at 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);
        });
    }

Upvotes: 1

Views: 1860

Answers (1)

Valentina Konyukhova
Valentina Konyukhova

Reputation: 5324

I faced the same issue in my ViewModel. Seems like it is an inner limitation of MediatorLiveData. If it sees that the same type of LiveData is added, it wants to have the same listener to work with it. I will just add my case as it was with the same type of error and after (no error, works fine). Code with error:

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

After the refactoring:

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

Upvotes: 1

Related Questions