blob: 2fcce55c9c1d403c34b28cf585fd43c630ddf2c9 [file] [log] [blame]
// 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);
}
}