简体   繁体   中英

Android LiveData, ViewModel, Cannot add the same observer with different lifecycles

I'm new in android architecture components, and trying to use LiveData in my activity and MyLifecycleService, but sometimes the app crashed with

IllegalArgumentException: Cannot add the same observer with different lifecycles

here is my code in service

 private final MutableLiveData<SocketStatus> socketStatusMutableLiveData = OrderRxRepository.Companion.getInstance().getMldSocketStatus(); 
 socketStatusMutableLiveData.observe(this, socketStatus -> {
        if (socketStatus == null) return;
        ...
    });

for my activity I have activityViewModel class which contains the same livedata, here is the code

class MyActivityViewModel: ViewModel() {
val socketStatusMutableLiveData = OrderRxRepository.instance.mldSocketStatus
}

and the code in my activity

MyActivityViewModel viewModel = ViewModelProviders.of(this).get(MyActivityViewModel .class);
viewModel.getSocketStatusMutableLiveData().observe(this, socketStatus -> {
        if (socketStatus == null) return;
        ...
    });

tl;dr You can't call LiveData.observe() with two different LifecycleOwner s. In your case, your Activity is one LifecycleOwner and the other is your Service.

From Android's source code you can see that this exception is thrown if there is already a LifecyclerOwner observing and that LifecyclerOwner is different from the one you are trying to observe with.

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
    ...
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    ...
}

This explains why you are having this problem since you are trying to observe on the same LiveData with an Activity (which is one LifecycleOwner ) and a Service (a different LifecycleOwner ).

The bigger problem is that you are trying to use LiveData for something it wasn't meant to do. LiveData is meant to hold data for a single LifecycleOwner while you are trying to make it hold data for multiple LifecycleOwner .

You should consider other solutions to the problem you tried to solve with LiveData . Here are some alternatives depending on your needs:

  • Global singleton - great if you want to keep some data in memory and have it accessible everywhere in your app. Use it with Rx if you want your data to be "observable"
  • LocalBroadcastManager - great if you want to communicate between your service and activity
  • Intent - great if you want to also make sure your activity is alive once your service completes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM