| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package org.chromium.base.supplier; |
| |
| import androidx.annotation.CallSuper; |
| import androidx.annotation.NonNull; |
| |
| import org.chromium.base.UnownedUserData; |
| import org.chromium.base.UnownedUserDataHost; |
| import org.chromium.base.UnownedUserDataKey; |
| import org.chromium.base.lifetime.DestroyChecker; |
| import org.chromium.base.lifetime.Destroyable; |
| |
| /** |
| * UnownedUserDataSupplier handles the combined lifecycle management for {@link UnownedUserData} |
| * and {@link DestroyableObservableSupplier}. It can be constructed anywhere |
| * but needs to be attached before it's accessible via {@link UnownedUserDataHost}. When destroyed, |
| * UnownedUserDataSupplier is detached from all hosts. |
| * |
| * <p> |
| * A functional implementation with best practices is defined in |
| * {@link UnownedUserDataSupplierTest}. |
| * <p> |
| * Classes that hold a reference to to the concrete implementation of this class are also in charge |
| * of its lifecycle. {@link #destroy} should be called when the applciation is shutting down. This |
| * will detach the {@link UnownedUserDataSupplier}, but it won't destroy the supplied object. |
| * <p> |
| * In practice, UnownedUserDataSupplier owners should declare and assign the supplier inline. This |
| * allows interop between other supplier implementations as well as use in activity constructors |
| * before {@link WindowAndroid} is created. See the example below: |
| * |
| * <pre> |
| * {@code |
| * UnownedUserDataSupplier<Foo> mFooSupplier = new FooSupplier(); |
| * ... |
| * // Sometime after WindowAndroid has been created. |
| * mFooSupplier.attach(mWindowAndroid.getUnownedUserDataHost()); |
| * } |
| * </pre> |
| * |
| * @param <E> The type of the data to be Supplied and stored in UnownedUserData. |
| * @see UnownedUserDataHost for more details on ownership and typical usage. |
| * @see UnownedUserDataKey for information about the type of key that is required. |
| * @see UnownedUserData for the marker interface used for this type of data. |
| */ |
| public abstract class UnownedUserDataSupplier<E> |
| extends ObservableSupplierImpl<E> implements Destroyable, UnownedUserData { |
| private final UnownedUserDataKey<UnownedUserDataSupplier<E>> mUudKey; |
| private final DestroyChecker mDestroyChecker = new DestroyChecker(); |
| |
| /** |
| * Constructs an UnownedUserDataSupplier. |
| * @param uudKey The {@link UnownedUserDataKey}, which is defined in subclasses. |
| */ |
| protected UnownedUserDataSupplier( |
| @NonNull UnownedUserDataKey<? extends UnownedUserDataSupplier<E>> uudKey) { |
| mUudKey = (UnownedUserDataKey<UnownedUserDataSupplier<E>>) uudKey; |
| } |
| |
| /** |
| * Attach to the specified host. |
| * @param host The host to attach the supplier to. |
| */ |
| public void attach(@NonNull UnownedUserDataHost host) { |
| mDestroyChecker.checkNotDestroyed(); |
| mUudKey.attachToHost(host, this); |
| } |
| |
| @Override |
| @CallSuper |
| public void destroy() { |
| mDestroyChecker.destroy(); |
| mUudKey.detachFromAllHosts(this); |
| } |
| } |