1 // Copyright 2019 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base.supplier; 6 7 import androidx.annotation.NonNull; 8 9 import org.chromium.base.Callback; 10 11 import java.lang.ref.WeakReference; 12 13 /** 14 * Helper class to handle safely querying a single instance of an object from an 15 * {@link ObservableSupplier}. 16 * 17 * Assuming the underlying {@link Supplier} gets set with a 18 * value, this class will guarantee only a single call makes it back to the passed in 19 * {@link Callback}. 20 * 21 * For {@link ObservableSupplier}s that already have a valid value set, this will have the same 22 * underlying behavior as {@link ObservableSupplierImpl}, which asynchronously triggers the callback 23 * when {@link ObservableSupplier#addObserver(Callback)} is called. 24 * 25 * This class does not hold a strong reference to the {@link ObservableSupplier}, but does hold a 26 * strong reference to the {@link Callback}. 27 * 28 * @param <E> The type of the wrapped object. 29 */ 30 public class OneShotCallback<E> { 31 private final Callback<E> mCallbackWrapper = new CallbackWrapper(); 32 private final WeakReference<ObservableSupplier<E>> mWeakSupplier; 33 private final Callback<E> mCallback; 34 35 /** 36 * Creates a {@link OneShotCallback} instance, automatically registering as an observer to 37 * {@code supplier} and waiting to trigger {@code callback}. 38 * @param supplier The {@link ObservableSupplier} to wait for. 39 * @param callback The {@link Callback} to notify with a valid value. 40 */ OneShotCallback(@onNull ObservableSupplier<E> supplier, @NonNull Callback<E> callback)41 public OneShotCallback(@NonNull ObservableSupplier<E> supplier, @NonNull Callback<E> callback) { 42 mWeakSupplier = new WeakReference<>(supplier); 43 mCallback = callback; 44 45 supplier.addObserver(mCallbackWrapper); 46 } 47 48 private class CallbackWrapper implements Callback<E> { 49 @Override onResult(E result)50 public void onResult(E result) { 51 mCallback.onResult(result); 52 ObservableSupplier<E> supplier = mWeakSupplier.get(); 53 assert supplier != null 54 : "This can only be called by supplier, which should not be null."; 55 supplier.removeObserver(mCallbackWrapper); 56 } 57 } 58 } 59