java.lang.IllegalArgumentException : This source was already added with the different observer 异常

标签 java android mvvm android-architecture-components android-livedata

任何人都可以为我正确解释这个表达式......这似乎是我目前面临的问题。

MediatorLiveData#addSource

Starts to listen the given source LiveData, onChanged observer will be called when source value was changed.

onChanged callback will be called only when this MediatorLiveData is active.

If the given LiveData is already added as a source but with a different Observer, IllegalArgumentException will be thrown.

我目前有以下作为我的 ViewModel(称为 SplashViewModel)

package com.testapp.testapp.ui.splash;

import com.testapp.testapp.repository.HealthTipRepository;

import javax.inject.Inject;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData;
import androidx.lifecycle.ViewModel;


public class SplashViewModel extends ViewModel {

    private final HealthTipRepository healthTipRepository;

    // Load Status will be used to fill up the progress bar inside the Activity
    private final MediatorLiveData<Integer> loadStatus = new MediatorLiveData<>();
    
    @Inject
    SplashViewModel(HealthTipRepository healthTipRepository) {
        this.healthTipRepository = healthTipRepository;
    }

    LiveData<Integer> observeLoadStatus() {
        loadStatus.addSource(healthTipRepository.createHealthTips(), healthTips -> {
            int currentValue = loadStatus.getValue();
            int newValue = currentValue != null ? currentValue + 25 : 25;
            loadStatus.setValue(newValue);
        });
    }
}

在 Activity 中,我有这个:

package com.testapp.testapp.ui.splash;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.view.View;
import android.widget.ProgressBar;

import com.testapp.testapp.R;
import com.testapp.testapp.storage.PrefManager;
import com.testapp.testapp.ui.BaseActivity;
import com.testapp.testapp.ui.FactoryViewModel;

import javax.inject.Inject;

import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProviders;
import butterknife.BindView;

// Base Activity has already injected the Dagger component
public class SplashActivity extends BaseActivity {

    @BindView(R.id.splash_progress)
    ProgressBar progressBar;

    @Inject
    FactoryViewModel factoryViewModel;
    private SplashViewModel viewModel;

    // PrefManager is responsible for managing shared preferences. It exposes a .get Method
    @Inject
    PrefManager prefManager;

    @Override
    protected void onCreate(@Nullable Bundle savedInstance) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash_activity);

        ButterKnife.bind(this);

        viewModel = ViewModelProviders.of(this, factoryViewModel).get(SplashViewModel.class);
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Performs checks to turn on location. The viewmodel is placed in the
        // onREsume to ensure that even when we leave the activity to turn on the
        // location and return, we can always start the viewmodel
        boolean turnedOnLocation = false;
        if (!turnedOnLocation) {
            startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
        }

        boolean appSetup = prefManager.get("app_setup", false);
        if (!appSetup) {
            viewModel.observeLoadStatus().observe(this, status -> {
                progressBar.setProgress(status + "");
            });
        }
    }
}

一切运行顺利,但是,当我离开此 Activity 并返回时,应用程序崩溃并出现错误:

Process: com.testapp.testapp, PID: 29865
java.lang.RuntimeException: Unable to resume activity {com.testapp.testapp/com.testapp.testapp.ui.splash.SplashActivity}: java.lang.IllegalArgumentException: This source was already added with the different observer
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3609)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3649)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1663)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6524)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:888)
 Caused by: java.lang.IllegalArgumentException: This source was already added with the different observer
    at androidx.lifecycle.MediatorLiveData.addSource(MediatorLiveData.java:89)
    at com.testapp.testapp.ui.splash.SplashViewModel.fetchSensorLocations(SplashViewModel.java:25)
    at com.testapp.testapp.ui.splash.SplashViewModel.observeLoadStatus(SplashViewModel.java:17)
    at com.testapp.testapp.ui.splash.SplashActivity.observeViewModels(SplashActivity.java:121)
    at com.testapp.testapp.ui.splash.SplashActivity.onResume(SplashActivity.java:77)
    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1355)
    at android.app.Activity.performResume(Activity.java:7138)

我将非常感谢您的解释以及为什么我一直收到此错误。

谢谢

最佳答案

您正在 MediatorLiveData 的同一源上设置 2 观察者。

只能为每个源设置 1 个观察者,否则会抛出 IllegalStateException,就像您的情况一样。

observe 方法从 onResume() 移至 onCreate()

当您将 Activity 置于后台时,ViewModel 不会被销毁。它仍然在内存中,等待 Activity 返回前台。它只有在 Activity 完全关闭时才会被销毁。

如果您想停止观察特定来源,只需使用removeSource()

如果您想再次开始观察源,请使用addSource()

关于java.lang.IllegalArgumentException : This source was already added with the different observer 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54063693/

相关文章:

wpf - 在 Wpf 中显示与 MVVM 中的 ListView 不同的 View (缩略图、详细信息列表)

java - 创建文本文件 Java 时出错

java - 关于优先使用组合而不是继承方法,策略模式

java - RabbitMQ Java 客户端到 Windows 服务总线

android - 从 DB 类或 MVC 中的数据模型类查询数据库?

android - Android Studio 3.1.3 中的错误 :'Failed to find style ' coordinatorLayout Style' in current theme'

Java Swing - 鼠标进入JFrame后组件消失

android - 渲染期间引发异常 : 16 (Details)

xamarin - 切换按钮单击项的可见性-Xamarin Forms

wpf - 如何在 WPF 中更改 DynamicResource