14

I have the following code in Activity

@Override
public void onPause() {
    super.onPause();

    if (isFinishing()) {
        final LiveData<StickyNoteConfig> stickyNoteConfigLiveData = StickyNoteConfigRepository.INSTANCE.getStickyNoteConfig(mAppWidgetId);
        stickyNoteConfigLiveData.removeObservers(this);
        stickyNoteConfigLiveData.observe(this, stickyNoteConfig -> {
            // Weird, I still can receive call back.
            // I thought "this" is no longer active?
        });
    }
}

I feel puzzled that, Observer is still being triggered, although this activity is already in onPause state? According to https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.State#STARTED

Started state for a LifecycleOwner. For an Activity, this state is reached in two cases:

after onStart call;
right before onPause call.

May I know why it is so?

Saikrishna Rajaraman
  • 3,205
  • 2
  • 16
  • 29
Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875
  • https://stackoverflow.com/a/52753984/5788247 – Shomu Oct 11 '18 at 07:19
  • just like Vairavan said,@Override public void onPause() { if (viewLifecycleOwner != null) { viewLifecycleOwner.getLifecycle().handleLifecycleEvent(Event.ON_PAUSE); } super.onPause(); } @Override public void onStop() { if (viewLifecycleOwner != null) { viewLifecycleOwner.getLifecycle().handleLifecycleEvent(Event.ON_STOP); } super.onStop(); } – Jenus Dong Jun 03 '20 at 09:55

5 Answers5

12

According to LiveData reference,

  1. LiveData is a data holder class that can be observed within a given lifecycle. This means that an Observer can be added in a pair with a LifecycleOwner, and this observer will be notified about modifications of the wrapped data only if the paired LifecycleOwner is in active state. LifecycleOwner is considered as active, if its state is STARTED or RESUMED.

  2. An observer added with a Lifecycle will be automatically removed if the corresponding Lifecycle moves to DESTROYED state.

Now, according to your situation here, LiveData receives updates for your observer (your activity) in onPause() method, because your observer is not already in DESTROYED state.

So LiveData is still active for receive updates according to these methods:

onActive() :

Called when the number of active observers change to 1 from 0. This callback can be used to know that this LiveData is being used thus should be kept up to date.

&

onInactive() :

Called when the number of active observers change from 1 to 0. This does not mean that there are no observers left, there may still be observers but their lifecycle states aren't STARTED or RESUMED (like an Activity in the back stack).

You can check if there are observers via hasObservers().


So when does observer (your activity) gets DESTROYED state?

For default implementation of LifeCycleOwner indicates that activity gets it's DESTROYED state once onDestroy() method is executed & after onPause() it follows reverse order of LifeCycle state RESUMED -> STARTED -> CREATED -> DESTROYED.

Check this lifecycle graph.

Hope it helps !

Jeel Vankhede
  • 11,592
  • 2
  • 28
  • 58
  • 2
    Note on "Inactive observers registered to watch LiveData objects aren't notified about changes.". I presumed during `onPause`, the `LifeCycleOwner` is considered in inactive state? If so, why it is still being notified? – Cheok Yan Cheng Oct 16 '18 at 12:51
  • 1
    No, **inactive observers** are removed once they reach **destroyed** state & `onPause` don't mean to be **destroyed** state for observers. – Jeel Vankhede Oct 16 '18 at 13:15
  • 2
    `onPause` mean observer is in inactive state. Isn't an inactive observer shouldn't receive notification? – Cheok Yan Cheng Oct 16 '18 at 13:17
2

https://medium.com/@hanyuliu/livedata-may-lose-data-2fffdac57dc9 has logs to explain this issue. And just like @Vairavan said,in pause state activity can be partially visible.

public enum State {

DESTROYED,

INITIALIZED,

CREATED,

STARTED,

RESUMED;

public boolean isAtLeast(@NonNull State state) {
    return compareTo(state) >= 0;
}

}

so, observer's isAlive judge according to isAtLeast(STARTED). when OnPause is called, activity does not become DESTROYED.

Jenus Dong
  • 304
  • 2
  • 7
0

This becomes obvious when onPause and onStop is related to UI side effects. An activity is paused and not stopped if any part of the activity window is still visible. This could happen when another activity is shown on top of the paused activity as a dialog. In this case, more often than not, developers would like the paused activity's UI to still be updated even though it is only partially visible. LiveData's update in this paused state helps do that.

There are other cases like multi-window feature. One activity could be paused while the user is interacting with another app/activity in a different window. Paused activity could be a video playback with active updates and should be updated even though user is interacting with another app. Note that this implementation is changing from Android P for foldable phones where multiple activities/windows could be in resumed state (that is not the concern for live data updates anyways). https://android-developers.googleblog.com/2018/11/get-your-app-ready-for-foldable-phones.html

Vairavan
  • 1,246
  • 1
  • 15
  • 19
0

Normally, onPause (without onStop) will happened when a partially of screen is cover by other screen (eg: notification from other app, or open a transparent activity).
Because, whole screen is not cover, so we may see some part of the current screen.
Therefore, I think LiveData may still need to notify in on pause state to make sure user always see the latest data.

If user go to background, or navigate to other screen, then the whole of screen is cover, we dont need to update UI because user dont see it. So LiveData dont need to notify in onStop state

Helpful answers: Android: Scenario where onPause is called but not onStop?

Linh
  • 57,942
  • 23
  • 262
  • 279
-1

LiveData only updates app component observers that are in an active lifecycle state.

If anyone wants to perform any lifecycle-related work they must override onActive() and onInActive() methods. eg:

public class StockLiveData extends LiveData<BigDecimal> {
...... 
@Override
    protected void onActive() {

    }

    @Override
    protected void onInactive() {

    }
}

Important Line:

An observer added with a Lifecycle will be automatically removed if the corresponding Lifecycle moves to DESTROYED state.

Jitesh Mohite
  • 31,138
  • 12
  • 157
  • 147