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 & 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