1c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar/*
264db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyar * Copyright (C) 2017 The Android Open Source Project
3c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar *
4c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
5c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * you may not use this file except in compliance with the License.
6c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * You may obtain a copy of the License at
7c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar *
8c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
9c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar *
10c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * Unless required by applicable law or agreed to in writing, software
11c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
12c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * See the License for the specific language governing permissions and
14c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * limitations under the License.
15c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar */
16c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
17ba069d50913c3fb250bb60ec310439db36895337Alan Viverettepackage androidx.lifecycle;
18c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
19ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport static androidx.lifecycle.Lifecycle.State.DESTROYED;
20ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport static androidx.lifecycle.Lifecycle.State.STARTED;
21c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
22ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.annotation.MainThread;
23ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.annotation.NonNull;
24ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.annotation.Nullable;
25ba069d50913c3fb250bb60ec310439db36895337Alan Viveretteimport androidx.arch.core.internal.SafeIterableMap;
26ddee2b5170ae257a7b2494f8aaa8459ebed806dcAurimas Liutikasimport androidx.arch.core.executor.ArchTaskExecutor;
27c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
28c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinetsimport java.util.Iterator;
29c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinetsimport java.util.Map;
30c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets
31c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar/**
32e69e470336d0b6a1b4a16fe1783af17143d0c426Sergey Vasilinets * LiveData is a data holder class that can be observed within a given lifecycle.
33e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets * This means that an {@link Observer} can be added in a pair with a {@link LifecycleOwner}, and
34e69e470336d0b6a1b4a16fe1783af17143d0c426Sergey Vasilinets * this observer will be notified about modifications of the wrapped data only if the paired
35e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets * LifecycleOwner is in active state. LifecycleOwner is considered as active, if its state is
3627015a7478beac9e231135207e3e705784cee508Sergey Vasilinets * {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}. An observer added via
3727015a7478beac9e231135207e3e705784cee508Sergey Vasilinets * {@link #observeForever(Observer)} is considered as always active and thus will be always notified
3827015a7478beac9e231135207e3e705784cee508Sergey Vasilinets * about modifications. For those observers, you should manually call
3927015a7478beac9e231135207e3e705784cee508Sergey Vasilinets * {@link #removeObserver(Observer)}.
40e69e470336d0b6a1b4a16fe1783af17143d0c426Sergey Vasilinets *
41e69e470336d0b6a1b4a16fe1783af17143d0c426Sergey Vasilinets * <p> An observer added with a Lifecycle will be automatically removed if the corresponding
4227015a7478beac9e231135207e3e705784cee508Sergey Vasilinets * Lifecycle moves to {@link Lifecycle.State#DESTROYED} state. This is especially useful for
4327015a7478beac9e231135207e3e705784cee508Sergey Vasilinets * activities and fragments where they can safely observe LiveData and not worry about leaks:
4427015a7478beac9e231135207e3e705784cee508Sergey Vasilinets * they will be instantly unsubscribed when they are destroyed.
45e69e470336d0b6a1b4a16fe1783af17143d0c426Sergey Vasilinets *
46e69e470336d0b6a1b4a16fe1783af17143d0c426Sergey Vasilinets * <p>
47e69e470336d0b6a1b4a16fe1783af17143d0c426Sergey Vasilinets * In addition, LiveData has {@link LiveData#onActive()} and {@link LiveData#onInactive()} methods
4889b6198c76e51a505556d7f4e57d3e48e24d5eceYigit Boyar * to get notified when number of active {@link Observer}s change between 0 and 1.
4989b6198c76e51a505556d7f4e57d3e48e24d5eceYigit Boyar * This allows LiveData to release any heavy resources when it does not have any Observers that
5089b6198c76e51a505556d7f4e57d3e48e24d5eceYigit Boyar * are actively observing.
51c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar * <p>
52e69e470336d0b6a1b4a16fe1783af17143d0c426Sergey Vasilinets * This class is designed to hold individual data fields of {@link ViewModel},
53e69e470336d0b6a1b4a16fe1783af17143d0c426Sergey Vasilinets * but can also be used for sharing data between different modules in your application
54e69e470336d0b6a1b4a16fe1783af17143d0c426Sergey Vasilinets * in a decoupled fashion.
55c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar *
565cfbb5dc6b92d9901a83628aec597acceb831916shepshapard * @param <T> The type of data held by this instance
57e69e470336d0b6a1b4a16fe1783af17143d0c426Sergey Vasilinets * @see ViewModel
58c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar */
59abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinetspublic abstract class LiveData<T> {
6034e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar    private final Object mDataLock = new Object();
616ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    static final int START_VERSION = -1;
62c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    private static final Object NOT_SET = new Object();
63c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
648054b2b48805260f3efb5afaad0b17b1378d13bdSergey Vasilinets    private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
65c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            new SafeIterableMap<>();
66c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
67c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    // how many observers are in active state
68c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    private int mActiveCount = 0;
690a44cc5ae154cf23753eca1c020bd6a9b30eeb0dSergey Vasilinets    private volatile Object mData = NOT_SET;
7034e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar    // when setData is called, we set the pending data and actual data swap happens on the main
7134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar    // thread
7234e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar    private volatile Object mPendingData = NOT_SET;
73c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    private int mVersion = START_VERSION;
74c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
75c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets    private boolean mDispatchingValue;
76c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets    @SuppressWarnings("FieldCanBeLocal")
77c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets    private boolean mDispatchInvalidated;
78459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets    private final Runnable mPostValueRunnable = new Runnable() {
79459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets        @Override
80459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets        public void run() {
81459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets            Object newValue;
82459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets            synchronized (mDataLock) {
83459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets                newValue = mPendingData;
84459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets                mPendingData = NOT_SET;
85459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets            }
86459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets            //noinspection unchecked
87459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets            setValue((T) newValue);
88459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets        }
89459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets    };
90c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets
91406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets    private void considerNotify(ObserverWrapper observer) {
92406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        if (!observer.mActive) {
93c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            return;
94c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        }
955dcab68c2e390acfb016cb889604b85e1257b02fYigit Boyar        // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
965dcab68c2e390acfb016cb889604b85e1257b02fYigit Boyar        //
975dcab68c2e390acfb016cb889604b85e1257b02fYigit Boyar        // we still first check observer.active to keep it as the entrance for events. So even if
985dcab68c2e390acfb016cb889604b85e1257b02fYigit Boyar        // the observer moved to an active state, if we've not received that event, we better not
995dcab68c2e390acfb016cb889604b85e1257b02fYigit Boyar        // notify for a more predictable notification order.
100406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        if (!observer.shouldBeActive()) {
1015cfbb5dc6b92d9901a83628aec597acceb831916shepshapard            observer.activeStateChanged(false);
1025dcab68c2e390acfb016cb889604b85e1257b02fYigit Boyar            return;
1035dcab68c2e390acfb016cb889604b85e1257b02fYigit Boyar        }
104406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        if (observer.mLastVersion >= mVersion) {
105c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            return;
106c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        }
107406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        observer.mLastVersion = mVersion;
108c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        //noinspection unchecked
109406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        observer.mObserver.onChanged((T) mData);
110c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets    }
111c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets
112406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets    private void dispatchingValue(@Nullable ObserverWrapper initiator) {
113c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        if (mDispatchingValue) {
114c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            mDispatchInvalidated = true;
115c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            return;
116c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        }
117c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        mDispatchingValue = true;
118c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        do {
119c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            mDispatchInvalidated = false;
120c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            if (initiator != null) {
121c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                considerNotify(initiator);
122c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                initiator = null;
123c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            } else {
1248054b2b48805260f3efb5afaad0b17b1378d13bdSergey Vasilinets                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
125c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
126c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                    considerNotify(iterator.next().getValue());
127c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                    if (mDispatchInvalidated) {
128c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                        break;
1294d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar                    }
1304d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar                }
131c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            }
132c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        } while (mDispatchInvalidated);
133c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        mDispatchingValue = false;
134c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets    }
135c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets
136c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    /**
137e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * Adds the given observer to the observers list within the lifespan of the given
138e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * owner. The events are dispatched on the main thread. If LiveData already has data
139e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * set, it will be delivered to the observer.
140c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * <p>
14127015a7478beac9e231135207e3e705784cee508Sergey Vasilinets     * The observer will only receive events if the owner is in {@link Lifecycle.State#STARTED}
14227015a7478beac9e231135207e3e705784cee508Sergey Vasilinets     * or {@link Lifecycle.State#RESUMED} state (active).
143c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * <p>
14427015a7478beac9e231135207e3e705784cee508Sergey Vasilinets     * If the owner moves to the {@link Lifecycle.State#DESTROYED} state, the observer will
145c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * automatically be removed.
146c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * <p>
147e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * When data changes while the {@code owner} is not active, it will not receive any updates.
148c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * If it becomes active again, it will receive the last available data automatically.
149c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * <p>
150e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * LiveData keeps a strong reference to the observer and the owner as long as the
151e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to
152e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * the observer &amp; the owner.
153c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * <p>
15427015a7478beac9e231135207e3e705784cee508Sergey Vasilinets     * If the given owner is already in {@link Lifecycle.State#DESTROYED} state, LiveData
155e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * ignores the call.
156c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * <p>
157e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * If the given owner, observer tuple is already in the list, the call is ignored.
158e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * If the observer is already in the list with another owner, LiveData throws an
159c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * {@link IllegalArgumentException}.
160c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     *
161e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * @param owner    The LifecycleOwner which controls the observer
162c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * @param observer The observer that will receive the events
163c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     */
164c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @MainThread
1658054b2b48805260f3efb5afaad0b17b1378d13bdSergey Vasilinets    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
1661e6eadb9fb537c6bd81cc6a50ab685711cd84fd9Sergey Vasilinets        assertMainThread("observe");
167e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
168c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar            // ignore
169c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar            return;
170c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        }
171e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
172406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
173406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        if (existing != null && !existing.isAttachedTo(owner)) {
174c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            throw new IllegalArgumentException("Cannot add the same observer"
175c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                    + " with different lifecycles");
176c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        }
177c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        if (existing != null) {
178c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            return;
179c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        }
180e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets        owner.getLifecycle().addObserver(wrapper);
181c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
182c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
183c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    /**
1847c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets     * Adds the given observer to the observers list. This call is similar to
185e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * {@link LiveData#observe(LifecycleOwner, Observer)} with a LifecycleOwner, which
1867c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets     * is always active. This means that the given observer will receive all events and will never
1877c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets     * be automatically removed. You should manually call {@link #removeObserver(Observer)} to stop
1887c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets     * observing this LiveData.
1897c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets     * While LiveData has one of such observers, it will be considered
1907c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets     * as active.
1917c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets     * <p>
192e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * If the observer was already added with an owner to this LiveData, LiveData throws an
1937c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets     * {@link IllegalArgumentException}.
194c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets     *
1957c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets     * @param observer The observer that will receive the events
1967c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets     */
1977c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets    @MainThread
1988054b2b48805260f3efb5afaad0b17b1378d13bdSergey Vasilinets    public void observeForever(@NonNull Observer<? super T> observer) {
1991e6eadb9fb537c6bd81cc6a50ab685711cd84fd9Sergey Vasilinets        assertMainThread("observeForever");
200406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
201406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
202406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
203406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            throw new IllegalArgumentException("Cannot add the same observer"
204406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets                    + " with different lifecycles");
205406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        }
206406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        if (existing != null) {
207406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            return;
208406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        }
209406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        wrapper.activeStateChanged(true);
2107c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets    }
2117c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets
2127c41ee306fc78feaa0043c65bf82e65935bd9d35Sergey Vasilinets    /**
213c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * Removes the given observer from the observers list.
214c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     *
215c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * @param observer The Observer to receive events.
216c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     */
217c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @MainThread
2188054b2b48805260f3efb5afaad0b17b1378d13bdSergey Vasilinets    public void removeObserver(@NonNull final Observer<? super T> observer) {
21934e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar        assertMainThread("removeObserver");
220406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        ObserverWrapper removed = mObservers.remove(observer);
221c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        if (removed == null) {
222c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            return;
223c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        }
224406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        removed.detachObserver();
225c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        removed.activeStateChanged(false);
226c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
227c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
228c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    /**
229e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * Removes all observers that are tied to the given {@link LifecycleOwner}.
230c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     *
231e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets     * @param owner The {@code LifecycleOwner} scope for the observers to be removed.
232c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     */
233406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets    @SuppressWarnings("WeakerAccess")
234c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @MainThread
2359d8d936607b58e83fbf1ef57b5bd9846829abb66Sergey Vasilinets    public void removeObservers(@NonNull final LifecycleOwner owner) {
23634e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar        assertMainThread("removeObservers");
2378054b2b48805260f3efb5afaad0b17b1378d13bdSergey Vasilinets        for (Map.Entry<Observer<? super T>, ObserverWrapper> entry : mObservers) {
238406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            if (entry.getValue().isAttachedTo(owner)) {
239c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                removeObserver(entry.getKey());
240c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar            }
241c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        }
242c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
243c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
244c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    /**
245459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * Posts a task to a main thread to set the given value. So if you have a following code
246459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * executed in the main thread:
247459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * <pre class="prettyprint">
248459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * liveData.postValue("a");
249459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * liveData.setValue("b");
250459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * </pre>
251459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * The value "b" would be set at first and later the main thread would override it with
252459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * the value "a".
25334e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar     * <p>
254459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * If you called this method multiple times before a main thread executed a posted task, only
255459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * the last value would be dispatched.
256c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     *
257c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * @param value The new value
258c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     */
2596ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    protected void postValue(T value) {
260459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets        boolean postTask;
26134e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar        synchronized (mDataLock) {
262459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets            postTask = mPendingData == NOT_SET;
26334e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar            mPendingData = value;
26434e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar        }
265459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets        if (!postTask) {
266459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets            return;
267459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets        }
268ae36c8b11a64d3cdc9ba6e37d9f3d1d250fdc4a8Yigit Boyar        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
269459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets    }
270459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets
271459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets    /**
272459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * Sets the value. If there are active observers, the value will be dispatched to them.
273459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * <p>
274459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * This method must be called from the main thread. If you need set a value from a background
275459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * thread, you can use {@link #postValue(Object)}
276459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     *
277459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     * @param value The new value
278459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets     */
279459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets    @MainThread
2806ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    protected void setValue(T value) {
281459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets        assertMainThread("setValue");
282459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets        mVersion++;
283459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets        mData = value;
284459caadc8f6875fc78a36ae716193bf991f0808cSergey Vasilinets        dispatchingValue(null);
285c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
286c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
287c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    /**
288c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * Returns the current value.
289c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * Note that calling this method on a background thread does not guarantee that the latest
290c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * value set will be received.
291c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     *
292c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * @return the current value
293c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     */
294c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    @Nullable
295c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    public T getValue() {
296c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        Object data = mData;
2970a44cc5ae154cf23753eca1c020bd6a9b30eeb0dSergey Vasilinets        if (data != NOT_SET) {
298c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar            //noinspection unchecked
2990a44cc5ae154cf23753eca1c020bd6a9b30eeb0dSergey Vasilinets            return (T) data;
300c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        }
301c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        return null;
302c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
303c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
3046ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    int getVersion() {
3056ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets        return mVersion;
3066ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets    }
3076ca8525782f16bcb4403dc692a1fefd77934aa31Sergey Vasilinets
308c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    /**
3095cf395a3446bc61c8f281464aa88e9cec2c0c177Florina Muntenescu     * Called when the number of active observers change to 1 from 0.
310c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * <p>
3114d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar     * This callback can be used to know that this LiveData is being used thus should be kept
3124d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar     * up to date.
313c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     */
3144d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    protected void onActive() {
3154d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
316c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
317c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
318c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    /**
3194d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar     * Called when the number of active observers change from 1 to 0.
320c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     * <p>
3214d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar     * This does not mean that there are no observers left, there may still be observers but their
32227015a7478beac9e231135207e3e705784cee508Sergey Vasilinets     * lifecycle states aren't {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}
32327015a7478beac9e231135207e3e705784cee508Sergey Vasilinets     * (like an Activity in the back stack).
3244d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar     * <p>
325abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets     * You can check if there are observers via {@link #hasObservers()}.
3264d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar     */
3274d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    protected void onInactive() {
3284d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
3294d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    }
3304d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar
3314d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    /**
332abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets     * Returns true if this LiveData has observers.
333c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     *
334abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets     * @return true if this LiveData has observers
335c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar     */
336406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets    @SuppressWarnings("WeakerAccess")
337abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets    public boolean hasObservers() {
338abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets        return mObservers.size() > 0;
339c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
340c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
3414d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    /**
342abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets     * Returns true if this LiveData has active observers.
3434d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar     *
344abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets     * @return true if this LiveData has active observers
3454d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar     */
346406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets    @SuppressWarnings("WeakerAccess")
347abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets    public boolean hasActiveObservers() {
348abf6c87826e1a86fed71d945dc7e7f1aa643ea6cSergey Vasilinets        return mActiveCount > 0;
3494d4bf0391459bec361ec7843447ae60d38c99028Yigit Boyar    }
350c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
351406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets    class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
352406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        @NonNull final LifecycleOwner mOwner;
353406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets
3548054b2b48805260f3efb5afaad0b17b1378d13bdSergey Vasilinets        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
355406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            super(observer);
356406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            mOwner = owner;
357406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        }
358c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
359406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        @Override
360406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        boolean shouldBeActive() {
361406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
362c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        }
363c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
364d99995d86cb9d0f97624181e5a553f1a0b8102a1Sergey Vasilinets        @Override
365d99995d86cb9d0f97624181e5a553f1a0b8102a1Sergey Vasilinets        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
366406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
367406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets                removeObserver(mObserver);
368c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar                return;
369c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar            }
370406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            activeStateChanged(shouldBeActive());
371406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        }
372406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets
373406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        @Override
374406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        boolean isAttachedTo(LifecycleOwner owner) {
375406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            return mOwner == owner;
376406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        }
377406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets
378406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        @Override
379406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        void detachObserver() {
380406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            mOwner.getLifecycle().removeObserver(this);
381406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        }
382406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets    }
383406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets
384406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets    private abstract class ObserverWrapper {
3858054b2b48805260f3efb5afaad0b17b1378d13bdSergey Vasilinets        final Observer<? super T> mObserver;
386406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        boolean mActive;
387406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        int mLastVersion = START_VERSION;
388406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets
3898054b2b48805260f3efb5afaad0b17b1378d13bdSergey Vasilinets        ObserverWrapper(Observer<? super T> observer) {
390406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            mObserver = observer;
391406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        }
392406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets
393406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        abstract boolean shouldBeActive();
394406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets
395406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        boolean isAttachedTo(LifecycleOwner owner) {
396406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            return false;
397406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        }
398406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets
399406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        void detachObserver() {
400c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        }
401c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
402c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets        void activeStateChanged(boolean newActive) {
403406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            if (newActive == mActive) {
404c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                return;
405c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            }
406406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            // immediately set active state, so we'd never dispatch anything to inactive
407406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            // owner
408406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            mActive = newActive;
4090da9764fa45b24977675265e04e8aff3fc889d04Sergey Vasilinets            boolean wasInactive = LiveData.this.mActiveCount == 0;
410406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            LiveData.this.mActiveCount += mActive ? 1 : -1;
411406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            if (wasInactive && mActive) {
412c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                onActive();
413c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            }
414406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            if (LiveData.this.mActiveCount == 0 && !mActive) {
415c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                onInactive();
416c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            }
417406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            if (mActive) {
418c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets                dispatchingValue(this);
419c43ce90b803cdfa033dfc94fa4161371ed6f3ec6Sergey Vasilinets            }
420c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar        }
421c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
422c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar
423406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets    private class AlwaysActiveObserver extends ObserverWrapper {
424406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets
4258054b2b48805260f3efb5afaad0b17b1378d13bdSergey Vasilinets        AlwaysActiveObserver(Observer<? super T> observer) {
426406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            super(observer);
427406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        }
428406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets
429406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        @Override
430406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        boolean shouldBeActive() {
431406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets            return true;
432406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets        }
433c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar    }
43434e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar
435406dfb7a30f9fb785412cbe4d4e75503c58dafd9Sergey Vasilinets    private static void assertMainThread(String methodName) {
436ae36c8b11a64d3cdc9ba6e37d9f3d1d250fdc4a8Yigit Boyar        if (!ArchTaskExecutor.getInstance().isMainThread()) {
43734e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar            throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
438d8ea6fa753372c38ad46211d871432363d8bd6c8Yigit Boyar                    + " thread");
43934e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar        }
44034e5031083f735db3a395b0f6aa430880b072d71Yigit Boyar    }
441c1b53ee5d095a74b84c21257fb4cd00e33f748baYigit Boyar}
442