| // Copyright 2019 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.NonNull; |
| |
| import org.chromium.base.Callback; |
| |
| import java.lang.ref.WeakReference; |
| |
| /** |
| * Helper class to handle safely querying a single instance of an object from an |
| * {@link ObservableSupplier}. |
| * |
| * Assuming the underlying {@link Supplier} gets set with a |
| * value, this class will guarantee only a single call makes it back to the passed in |
| * {@link Callback}. |
| * |
| * For {@link ObservableSupplier}s that already have a valid value set, this will have the same |
| * underlying behavior as {@link ObservableSupplierImpl}, which asynchronously triggers the callback |
| * when {@link ObservableSupplier#addObserver(Callback)} is called. |
| * |
| * This class does not hold a strong reference to the {@link ObservableSupplier}, but does hold a |
| * strong reference to the {@link Callback}. |
| * |
| * @param <E> The type of the wrapped object. |
| */ |
| public class OneShotCallback<E> { |
| private final Callback<E> mCallbackWrapper = new CallbackWrapper(); |
| private final WeakReference<ObservableSupplier<E>> mWeakSupplier; |
| private final Callback<E> mCallback; |
| |
| /** |
| * Creates a {@link OneShotCallback} instance, automatically registering as an observer to |
| * {@code supplier} and waiting to trigger {@code callback}. |
| * @param supplier The {@link ObservableSupplier} to wait for. |
| * @param callback The {@link Callback} to notify with a valid value. |
| */ |
| public OneShotCallback(@NonNull ObservableSupplier<E> supplier, @NonNull Callback<E> callback) { |
| mWeakSupplier = new WeakReference<>(supplier); |
| mCallback = callback; |
| |
| supplier.addObserver(mCallbackWrapper); |
| } |
| |
| private class CallbackWrapper implements Callback<E> { |
| @Override |
| public void onResult(E result) { |
| mCallback.onResult(result); |
| ObservableSupplier<E> supplier = mWeakSupplier.get(); |
| assert supplier != null |
| : "This can only be called by supplier, which should not be null."; |
| supplier.removeObserver(mCallbackWrapper); |
| } |
| } |
| } |