1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.lifecycle;
18 
19 import static androidx.lifecycle.Lifecycle.State.DESTROYED;
20 import static androidx.lifecycle.Lifecycle.State.STARTED;
21 
22 import androidx.annotation.MainThread;
23 import androidx.annotation.NonNull;
24 import androidx.annotation.Nullable;
25 import androidx.arch.core.internal.SafeIterableMap;
26 import androidx.arch.core.executor.ArchTaskExecutor;
27 
28 import java.util.Iterator;
29 import java.util.Map;
30 
31 /**
32  * LiveData is a data holder class that can be observed within a given lifecycle.
33  * This means that an {@link Observer} can be added in a pair with a {@link LifecycleOwner}, and
34  * this observer will be notified about modifications of the wrapped data only if the paired
35  * LifecycleOwner is in active state. LifecycleOwner is considered as active, if its state is
36  * {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}. An observer added via
37  * {@link #observeForever(Observer)} is considered as always active and thus will be always notified
38  * about modifications. For those observers, you should manually call
39  * {@link #removeObserver(Observer)}.
40  *
41  * <p> An observer added with a Lifecycle will be automatically removed if the corresponding
42  * Lifecycle moves to {@link Lifecycle.State#DESTROYED} state. This is especially useful for
43  * activities and fragments where they can safely observe LiveData and not worry about leaks:
44  * they will be instantly unsubscribed when they are destroyed.
45  *
46  * <p>
47  * In addition, LiveData has {@link LiveData#onActive()} and {@link LiveData#onInactive()} methods
48  * to get notified when number of active {@link Observer}s change between 0 and 1.
49  * This allows LiveData to release any heavy resources when it does not have any Observers that
50  * are actively observing.
51  * <p>
52  * This class is designed to hold individual data fields of {@link ViewModel},
53  * but can also be used for sharing data between different modules in your application
54  * in a decoupled fashion.
55  *
56  * @param <T> The type of data held by this instance
57  * @see ViewModel
58  */
59 public abstract class LiveData<T> {
60     private final Object mDataLock = new Object();
61     static final int START_VERSION = -1;
62     private static final Object NOT_SET = new Object();
63 
64     private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
65             new SafeIterableMap<>();
66 
67     // how many observers are in active state
68     private int mActiveCount = 0;
69     private volatile Object mData = NOT_SET;
70     // when setData is called, we set the pending data and actual data swap happens on the main
71     // thread
72     private volatile Object mPendingData = NOT_SET;
73     private int mVersion = START_VERSION;
74 
75     private boolean mDispatchingValue;
76     @SuppressWarnings("FieldCanBeLocal")
77     private boolean mDispatchInvalidated;
78     private final Runnable mPostValueRunnable = new Runnable() {
79         @Override
80         public void run() {
81             Object newValue;
82             synchronized (mDataLock) {
83                 newValue = mPendingData;
84                 mPendingData = NOT_SET;
85             }
86             //noinspection unchecked
87             setValue((T) newValue);
88         }
89     };
90 
considerNotify(ObserverWrapper observer)91     private void considerNotify(ObserverWrapper observer) {
92         if (!observer.mActive) {
93             return;
94         }
95         // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
96         //
97         // we still first check observer.active to keep it as the entrance for events. So even if
98         // the observer moved to an active state, if we've not received that event, we better not
99         // notify for a more predictable notification order.
100         if (!observer.shouldBeActive()) {
101             observer.activeStateChanged(false);
102             return;
103         }
104         if (observer.mLastVersion >= mVersion) {
105             return;
106         }
107         observer.mLastVersion = mVersion;
108         //noinspection unchecked
109         observer.mObserver.onChanged((T) mData);
110     }
111 
dispatchingValue(@ullable ObserverWrapper initiator)112     private void dispatchingValue(@Nullable ObserverWrapper initiator) {
113         if (mDispatchingValue) {
114             mDispatchInvalidated = true;
115             return;
116         }
117         mDispatchingValue = true;
118         do {
119             mDispatchInvalidated = false;
120             if (initiator != null) {
121                 considerNotify(initiator);
122                 initiator = null;
123             } else {
124                 for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
125                         mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
126                     considerNotify(iterator.next().getValue());
127                     if (mDispatchInvalidated) {
128                         break;
129                     }
130                 }
131             }
132         } while (mDispatchInvalidated);
133         mDispatchingValue = false;
134     }
135 
136     /**
137      * Adds the given observer to the observers list within the lifespan of the given
138      * owner. The events are dispatched on the main thread. If LiveData already has data
139      * set, it will be delivered to the observer.
140      * <p>
141      * The observer will only receive events if the owner is in {@link Lifecycle.State#STARTED}
142      * or {@link Lifecycle.State#RESUMED} state (active).
143      * <p>
144      * If the owner moves to the {@link Lifecycle.State#DESTROYED} state, the observer will
145      * automatically be removed.
146      * <p>
147      * When data changes while the {@code owner} is not active, it will not receive any updates.
148      * If it becomes active again, it will receive the last available data automatically.
149      * <p>
150      * LiveData keeps a strong reference to the observer and the owner as long as the
151      * given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to
152      * the observer &amp; the owner.
153      * <p>
154      * If the given owner is already in {@link Lifecycle.State#DESTROYED} state, LiveData
155      * ignores the call.
156      * <p>
157      * If the given owner, observer tuple is already in the list, the call is ignored.
158      * If the observer is already in the list with another owner, LiveData throws an
159      * {@link IllegalArgumentException}.
160      *
161      * @param owner    The LifecycleOwner which controls the observer
162      * @param observer The observer that will receive the events
163      */
164     @MainThread
observe(@onNull LifecycleOwner owner, @NonNull Observer<? super T> observer)165     public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
166         assertMainThread("observe");
167         if (owner.getLifecycle().getCurrentState() == DESTROYED) {
168             // ignore
169             return;
170         }
171         LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
172         ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
173         if (existing != null && !existing.isAttachedTo(owner)) {
174             throw new IllegalArgumentException("Cannot add the same observer"
175                     + " with different lifecycles");
176         }
177         if (existing != null) {
178             return;
179         }
180         owner.getLifecycle().addObserver(wrapper);
181     }
182 
183     /**
184      * Adds the given observer to the observers list. This call is similar to
185      * {@link LiveData#observe(LifecycleOwner, Observer)} with a LifecycleOwner, which
186      * is always active. This means that the given observer will receive all events and will never
187      * be automatically removed. You should manually call {@link #removeObserver(Observer)} to stop
188      * observing this LiveData.
189      * While LiveData has one of such observers, it will be considered
190      * as active.
191      * <p>
192      * If the observer was already added with an owner to this LiveData, LiveData throws an
193      * {@link IllegalArgumentException}.
194      *
195      * @param observer The observer that will receive the events
196      */
197     @MainThread
observeForever(@onNull Observer<? super T> observer)198     public void observeForever(@NonNull Observer<? super T> observer) {
199         assertMainThread("observeForever");
200         AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
201         ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
202         if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
203             throw new IllegalArgumentException("Cannot add the same observer"
204                     + " with different lifecycles");
205         }
206         if (existing != null) {
207             return;
208         }
209         wrapper.activeStateChanged(true);
210     }
211 
212     /**
213      * Removes the given observer from the observers list.
214      *
215      * @param observer The Observer to receive events.
216      */
217     @MainThread
removeObserver(@onNull final Observer<? super T> observer)218     public void removeObserver(@NonNull final Observer<? super T> observer) {
219         assertMainThread("removeObserver");
220         ObserverWrapper removed = mObservers.remove(observer);
221         if (removed == null) {
222             return;
223         }
224         removed.detachObserver();
225         removed.activeStateChanged(false);
226     }
227 
228     /**
229      * Removes all observers that are tied to the given {@link LifecycleOwner}.
230      *
231      * @param owner The {@code LifecycleOwner} scope for the observers to be removed.
232      */
233     @SuppressWarnings("WeakerAccess")
234     @MainThread
removeObservers(@onNull final LifecycleOwner owner)235     public void removeObservers(@NonNull final LifecycleOwner owner) {
236         assertMainThread("removeObservers");
237         for (Map.Entry<Observer<? super T>, ObserverWrapper> entry : mObservers) {
238             if (entry.getValue().isAttachedTo(owner)) {
239                 removeObserver(entry.getKey());
240             }
241         }
242     }
243 
244     /**
245      * Posts a task to a main thread to set the given value. So if you have a following code
246      * executed in the main thread:
247      * <pre class="prettyprint">
248      * liveData.postValue("a");
249      * liveData.setValue("b");
250      * </pre>
251      * The value "b" would be set at first and later the main thread would override it with
252      * the value "a".
253      * <p>
254      * If you called this method multiple times before a main thread executed a posted task, only
255      * the last value would be dispatched.
256      *
257      * @param value The new value
258      */
postValue(T value)259     protected void postValue(T value) {
260         boolean postTask;
261         synchronized (mDataLock) {
262             postTask = mPendingData == NOT_SET;
263             mPendingData = value;
264         }
265         if (!postTask) {
266             return;
267         }
268         ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
269     }
270 
271     /**
272      * Sets the value. If there are active observers, the value will be dispatched to them.
273      * <p>
274      * This method must be called from the main thread. If you need set a value from a background
275      * thread, you can use {@link #postValue(Object)}
276      *
277      * @param value The new value
278      */
279     @MainThread
setValue(T value)280     protected void setValue(T value) {
281         assertMainThread("setValue");
282         mVersion++;
283         mData = value;
284         dispatchingValue(null);
285     }
286 
287     /**
288      * Returns the current value.
289      * Note that calling this method on a background thread does not guarantee that the latest
290      * value set will be received.
291      *
292      * @return the current value
293      */
294     @Nullable
getValue()295     public T getValue() {
296         Object data = mData;
297         if (data != NOT_SET) {
298             //noinspection unchecked
299             return (T) data;
300         }
301         return null;
302     }
303 
getVersion()304     int getVersion() {
305         return mVersion;
306     }
307 
308     /**
309      * Called when the number of active observers change to 1 from 0.
310      * <p>
311      * This callback can be used to know that this LiveData is being used thus should be kept
312      * up to date.
313      */
onActive()314     protected void onActive() {
315 
316     }
317 
318     /**
319      * Called when the number of active observers change from 1 to 0.
320      * <p>
321      * This does not mean that there are no observers left, there may still be observers but their
322      * lifecycle states aren't {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}
323      * (like an Activity in the back stack).
324      * <p>
325      * You can check if there are observers via {@link #hasObservers()}.
326      */
onInactive()327     protected void onInactive() {
328 
329     }
330 
331     /**
332      * Returns true if this LiveData has observers.
333      *
334      * @return true if this LiveData has observers
335      */
336     @SuppressWarnings("WeakerAccess")
hasObservers()337     public boolean hasObservers() {
338         return mObservers.size() > 0;
339     }
340 
341     /**
342      * Returns true if this LiveData has active observers.
343      *
344      * @return true if this LiveData has active observers
345      */
346     @SuppressWarnings("WeakerAccess")
hasActiveObservers()347     public boolean hasActiveObservers() {
348         return mActiveCount > 0;
349     }
350 
351     class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
352         @NonNull final LifecycleOwner mOwner;
353 
LifecycleBoundObserver(@onNull LifecycleOwner owner, Observer<? super T> observer)354         LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
355             super(observer);
356             mOwner = owner;
357         }
358 
359         @Override
shouldBeActive()360         boolean shouldBeActive() {
361             return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
362         }
363 
364         @Override
onStateChanged(LifecycleOwner source, Lifecycle.Event event)365         public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
366             if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
367                 removeObserver(mObserver);
368                 return;
369             }
370             activeStateChanged(shouldBeActive());
371         }
372 
373         @Override
isAttachedTo(LifecycleOwner owner)374         boolean isAttachedTo(LifecycleOwner owner) {
375             return mOwner == owner;
376         }
377 
378         @Override
detachObserver()379         void detachObserver() {
380             mOwner.getLifecycle().removeObserver(this);
381         }
382     }
383 
384     private abstract class ObserverWrapper {
385         final Observer<? super T> mObserver;
386         boolean mActive;
387         int mLastVersion = START_VERSION;
388 
ObserverWrapper(Observer<? super T> observer)389         ObserverWrapper(Observer<? super T> observer) {
390             mObserver = observer;
391         }
392 
shouldBeActive()393         abstract boolean shouldBeActive();
394 
isAttachedTo(LifecycleOwner owner)395         boolean isAttachedTo(LifecycleOwner owner) {
396             return false;
397         }
398 
detachObserver()399         void detachObserver() {
400         }
401 
activeStateChanged(boolean newActive)402         void activeStateChanged(boolean newActive) {
403             if (newActive == mActive) {
404                 return;
405             }
406             // immediately set active state, so we'd never dispatch anything to inactive
407             // owner
408             mActive = newActive;
409             boolean wasInactive = LiveData.this.mActiveCount == 0;
410             LiveData.this.mActiveCount += mActive ? 1 : -1;
411             if (wasInactive && mActive) {
412                 onActive();
413             }
414             if (LiveData.this.mActiveCount == 0 && !mActive) {
415                 onInactive();
416             }
417             if (mActive) {
418                 dispatchingValue(this);
419             }
420         }
421     }
422 
423     private class AlwaysActiveObserver extends ObserverWrapper {
424 
AlwaysActiveObserver(Observer<? super T> observer)425         AlwaysActiveObserver(Observer<? super T> observer) {
426             super(observer);
427         }
428 
429         @Override
shouldBeActive()430         boolean shouldBeActive() {
431             return true;
432         }
433     }
434 
assertMainThread(String methodName)435     private static void assertMainThread(String methodName) {
436         if (!ArchTaskExecutor.getInstance().isMainThread()) {
437             throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
438                     + " thread");
439         }
440     }
441 }
442