blob: c11b78a890b4e45d2927898be7216eb441c4e1f8 [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 application 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);
}
}