/
githubmirror
/
RxJava
Обзор
Документация
Войти
/
githubmirror
/
RxJava
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
4.x
src/main/java/io/reactivex/rxjava4/plugins/RxJavaPlugins.java
1 540 строк
57 KB
David Karnok
4.x: Streamable + takeUntil + groupBy + refactor + helpers (#8215)
05 июл 2026, 01:45
Не верифицирован
05 июл 2026, 01:45
580b39c
Код
Авторство
О чём код?
/* * Copyright (c) 2016-present, RxJava Contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See * the License for the specific language governing permissions and limitations under the License. */ package io.reactivex.rxjava4.plugins; import java.lang.Thread.UncaughtExceptionHandler; import java.util.Objects; import java.util.concurrent.*; import java.util.concurrent.Flow.Subscriber; import io.reactivex.rxjava4.annotations.*; import io.reactivex.rxjava4.core.*; import io.reactivex.rxjava4.exceptions.*; import io.reactivex.rxjava4.functions.*; import io.reactivex.rxjava4.internal.schedulers.*; import io.reactivex.rxjava4.internal.util.ExceptionHelper; import io.reactivex.rxjava4.parallel.ParallelFlowable; import io.reactivex.rxjava4.schedulers.Schedulers; /** * Utility class to inject handlers to certain standard RxJava operations. */ public final class RxJavaPlugins { @Nullable static volatile Consumer<? super Throwable> errorHandler; @Nullable static volatile Function<? super Runnable, ? extends Runnable> onScheduleHandler; @Nullable static volatile Function<? super Supplier<Scheduler>, ? extends Scheduler> onInitComputationHandler; @Nullable static volatile Function<? super Supplier<Scheduler>, ? extends Scheduler> onInitSingleHandler; @Nullable static volatile Function<? super Supplier<Scheduler>, ? extends Scheduler> onInitCachedHandler; @Nullable static volatile Function<? super Supplier<Scheduler>, ? extends Scheduler> onInitVirtualHandler; @Nullable static volatile Function<? super Supplier<Scheduler>, ? extends Scheduler> onInitNewThreadHandler; @Nullable static volatile Function<? super Scheduler, ? extends Scheduler> onComputationHandler; @Nullable static volatile Function<? super Scheduler, ? extends Scheduler> onSingleHandler; @Nullable static volatile Function<? super Scheduler, ? extends Scheduler> onCachedHandler; @Nullable static volatile Function<? super Scheduler, ? extends Scheduler> onVirtualHandler; @Nullable static volatile Function<? super Scheduler, ? extends Scheduler> onNewThreadHandler; @SuppressWarnings("rawtypes") @Nullable static volatile Function<? super Flowable, ? extends Flowable> onFlowableAssembly; @SuppressWarnings("rawtypes") @Nullable static volatile Function<? super ConnectableFlowable, ? extends ConnectableFlowable> onConnectableFlowableAssembly; @SuppressWarnings("rawtypes") @Nullable static volatile Function<? super Observable, ? extends Observable> onObservableAssembly; @SuppressWarnings("rawtypes") @Nullable static volatile Function<? super ConnectableObservable, ? extends ConnectableObservable> onConnectableObservableAssembly; @SuppressWarnings("rawtypes") @Nullable static volatile Function<? super Maybe, ? extends Maybe> onMaybeAssembly; @SuppressWarnings("rawtypes") @Nullable static volatile Function<? super Single, ? extends Single> onSingleAssembly; @Nullable static volatile Function<? super Completable, ? extends Completable> onCompletableAssembly; @SuppressWarnings("rawtypes") @Nullable static volatile Function<? super ParallelFlowable, ? extends ParallelFlowable> onParallelAssembly; @SuppressWarnings("rawtypes") @Nullable static volatile Function<? super Streamable, ? extends Streamable> onStreamableAssembly; @SuppressWarnings("rawtypes") @Nullable static volatile BiFunction<? super Flowable, @NonNull ? super Subscriber, @NonNull ? extends Subscriber> onFlowableSubscribe; @SuppressWarnings("rawtypes") @Nullable static volatile BiFunction<? super Maybe, @NonNull ? super MaybeObserver, @NonNull ? extends MaybeObserver> onMaybeSubscribe; @SuppressWarnings("rawtypes") @Nullable static volatile BiFunction<? super Observable, @NonNull ? super Observer, @NonNull ? extends Observer> onObservableSubscribe; @SuppressWarnings("rawtypes") @Nullable static volatile BiFunction<? super Single, @NonNull ? super SingleObserver, @NonNull ? extends SingleObserver> onSingleSubscribe; @Nullable static volatile BiFunction<? super Completable, @NonNull ? super CompletableObserver, @NonNull ? extends CompletableObserver> onCompletableSubscribe; @SuppressWarnings("rawtypes") @Nullable static volatile BiFunction<? super ParallelFlowable, @NonNull ? super Subscriber<@NonNull ?>[], @NonNull ? extends Subscriber<@NonNull ?>[]> onParallelSubscribe; @Nullable static volatile BooleanSupplier onBeforeBlocking; /** Prevents changing the plugins. */ static volatile boolean lockdown; /** * If true, attempting to run a blockingX operation on a (by default) * computation or single scheduler will throw an IllegalStateException. */ static volatile boolean failNonBlockingScheduler; /** * Prevents changing the plugins from then on. * <p>This allows container-like environments to prevent clients * messing with plugins. */ public static void lockdown() { lockdown = true; } /** * Returns true if the plugins were locked down. * @return true if the plugins were locked down */ public static boolean isLockdown() { return lockdown; } /** * Enables or disables the blockingX operators to fail * with an IllegalStateException on a non-blocking * scheduler such as computation or single. * <p>History: 2.0.5 - experimental * @param enable enable or disable the feature * @since 2.1 */ public static void setFailOnNonBlockingScheduler(boolean enable) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } failNonBlockingScheduler = enable; } /** * Returns true if the blockingX operators fail * with an IllegalStateException on a non-blocking scheduler * such as computation or single. * <p>History: 2.0.5 - experimental * @return true if the blockingX operators fail on a non-blocking scheduler * @since 2.1 */ public static boolean isFailOnNonBlockingScheduler() { return failNonBlockingScheduler; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Scheduler, ? extends Scheduler> getComputationSchedulerHandler() { return onComputationHandler; } /** * Returns the hook consumer. * @return the hook consumer, may be null */ @Nullable public static Consumer<? super Throwable> getErrorHandler() { return errorHandler; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Supplier<Scheduler>, ? extends Scheduler> getInitComputationSchedulerHandler() { return onInitComputationHandler; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Supplier<Scheduler>, ? extends Scheduler> getInitCachedSchedulerHandler() { return onInitCachedHandler; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Supplier<Scheduler>, ? extends Scheduler> getInitVirtualSchedulerHandler() { return onInitVirtualHandler; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Supplier<Scheduler>, ? extends Scheduler> getInitNewThreadSchedulerHandler() { return onInitNewThreadHandler; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Supplier<Scheduler>, ? extends Scheduler> getInitSingleSchedulerHandler() { return onInitSingleHandler; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Scheduler, ? extends Scheduler> getCachedSchedulerHandler() { return onCachedHandler; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Scheduler, ? extends Scheduler> getVirtualSchedulerHandler() { return onVirtualHandler; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Scheduler, ? extends Scheduler> getNewThreadSchedulerHandler() { return onNewThreadHandler; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Runnable, ? extends Runnable> getScheduleHandler() { return onScheduleHandler; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Scheduler, ? extends Scheduler> getSingleSchedulerHandler() { return onSingleHandler; } /** * Calls the associated hook function. * @param defaultScheduler a {@link Supplier} which returns the hook's input value * @return the value returned by the hook, not null * @throws NullPointerException if the supplier parameter or its result are null */ @NonNull public static Scheduler initComputationScheduler(@NonNull Supplier<Scheduler> defaultScheduler) { Objects.requireNonNull(defaultScheduler, "Scheduler Supplier can't be null"); Function<? super Supplier<Scheduler>, ? extends Scheduler> f = onInitComputationHandler; if (f == null) { return callRequireNonNull(defaultScheduler); } return applyRequireNonNull(f, defaultScheduler); // JIT will skip this } /** * Calls the associated hook function. * @param defaultScheduler a {@link Supplier} which returns the hook's input value * @return the value returned by the hook, not null * @throws NullPointerException if the supplier parameter or its result are null */ @NonNull public static Scheduler initCachedScheduler(@NonNull Supplier<Scheduler> defaultScheduler) { Objects.requireNonNull(defaultScheduler, "Scheduler Supplier can't be null"); Function<? super Supplier<Scheduler>, ? extends Scheduler> f = onInitCachedHandler; if (f == null) { return callRequireNonNull(defaultScheduler); } return applyRequireNonNull(f, defaultScheduler); } /** * Calls the associated hook function. * @param defaultScheduler a {@link Supplier} which returns the hook's input value * @return the value returned by the hook, not null * @throws NullPointerException if the supplier parameter or its result are null */ @NonNull public static Scheduler initVirtualScheduler(@NonNull Supplier<Scheduler> defaultScheduler) { Objects.requireNonNull(defaultScheduler, "Scheduler Supplier can't be null"); Function<? super Supplier<Scheduler>, ? extends Scheduler> f = onInitVirtualHandler; if (f == null) { return callRequireNonNull(defaultScheduler); } return applyRequireNonNull(f, defaultScheduler); } /** * Calls the associated hook function. * @param defaultScheduler a {@link Supplier} which returns the hook's input value * @return the value returned by the hook, not null * @throws NullPointerException if the supplier parameter or its result are null */ @NonNull public static Scheduler initNewThreadScheduler(@NonNull Supplier<Scheduler> defaultScheduler) { Objects.requireNonNull(defaultScheduler, "Scheduler Supplier can't be null"); Function<? super Supplier<Scheduler>, ? extends Scheduler> f = onInitNewThreadHandler; if (f == null) { return callRequireNonNull(defaultScheduler); } return applyRequireNonNull(f, defaultScheduler); } /** * Calls the associated hook function. * @param defaultScheduler a {@link Supplier} which returns the hook's input value * @return the value returned by the hook, not null * @throws NullPointerException if the supplier parameter or its result are null */ @NonNull public static Scheduler initSingleScheduler(@NonNull Supplier<Scheduler> defaultScheduler) { Objects.requireNonNull(defaultScheduler, "Scheduler Supplier can't be null"); Function<? super Supplier<Scheduler>, ? extends Scheduler> f = onInitSingleHandler; if (f == null) { return callRequireNonNull(defaultScheduler); } return applyRequireNonNull(f, defaultScheduler); } /** * Calls the associated hook function. * @param defaultScheduler the hook's input value * @return the value returned by the hook */ @NonNull public static Scheduler onComputationScheduler(@NonNull Scheduler defaultScheduler) { Function<? super Scheduler, ? extends Scheduler> f = onComputationHandler; if (f == null) { return defaultScheduler; } return apply(f, defaultScheduler); } /** * Called when an undeliverable error occurs. * <p> * Undeliverable errors are those {@code Observer.onError()} invocations that are not allowed to happen on * the given consumer type ({@code Observer}, {@code Subscriber}, etc.) due to protocol restrictions * because the consumer has either disposed/cancelled its {@code Disposable}/{@code Subscription} or * has already terminated with an {@code onError()} or {@code onComplete()} signal. * <p> * By default, this global error handler prints the stacktrace via {@link Throwable#printStackTrace()} * and calls {@link java.lang.Thread.UncaughtExceptionHandler#uncaughtException(Thread, Throwable)} * on the current thread. * <p> * Note that on some platforms, the platform runtime terminates the current application with an error if such * uncaught exceptions happen. In this case, it is recommended the application installs a global error * handler via the {@link #setErrorHandler(Consumer)} plugin method. * * @param error the error to report * @see #getErrorHandler() * @see #setErrorHandler(Consumer) * @see <a href="https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling">Error handling Wiki</a> */ public static void onError(@NonNull Throwable error) { Consumer<? super Throwable> f = errorHandler; if (error == null) { error = ExceptionHelper.createNullPointerException("onError called with a null Throwable."); } else { if (!isBug(error)) { error = new UndeliverableException(error); } } if (f != null) { try { f.accept(error); return; } catch (Throwable e) { // Exceptions.throwIfFatal(e); TODO decide e.printStackTrace(); // NOPMD uncaught(e); } } error.printStackTrace(); // NOPMD uncaught(error); } /** * Checks if the given error is one of the already named * bug cases that should pass through {@link #onError(Throwable)} * as is. * @param error the error to check * @return true if the error should pass through, false if * it may be wrapped into an UndeliverableException */ static boolean isBug(Throwable error) { // user forgot to add the onError handler in subscribe if (error instanceof OnErrorNotImplementedException) { return true; } // the sender didn't honor the request amount if (error instanceof MissingBackpressureException) { return true; } // it's either due to an operator bug or concurrent onNext if (error instanceof QueueOverflowException) { return true; } // general protocol violations // it's either due to an operator bug or concurrent onNext if (error instanceof IllegalStateException) { return true; } // nulls are generally not allowed // likely an operator bug or missing null-check if (error instanceof NullPointerException) { return true; } // bad arguments, likely invalid user input if (error instanceof IllegalArgumentException) { return true; } // Crash while handling an exception if (error instanceof CompositeException) { return true; } // everything else is probably due to lifecycle limits return false; } static void uncaught(@NonNull Throwable error) { Thread currentThread = Thread.currentThread(); UncaughtExceptionHandler handler = currentThread.getUncaughtExceptionHandler(); handler.uncaughtException(currentThread, error); } /** * Calls the associated hook function. * @param defaultScheduler the hook's input value * @return the value returned by the hook */ @NonNull public static Scheduler onCachedScheduler(@NonNull Scheduler defaultScheduler) { Function<? super Scheduler, ? extends Scheduler> f = onCachedHandler; if (f == null) { return defaultScheduler; } return apply(f, defaultScheduler); } /** * Calls the associated hook function. * @param defaultScheduler the hook's input value * @return the value returned by the hook */ @NonNull public static Scheduler onVirtualScheduler(@NonNull Scheduler defaultScheduler) { Function<? super Scheduler, ? extends Scheduler> f = onVirtualHandler; if (f == null) { return defaultScheduler; } return apply(f, defaultScheduler); } /** * Calls the associated hook function. * @param defaultScheduler the hook's input value * @return the value returned by the hook */ @NonNull public static Scheduler onNewThreadScheduler(@NonNull Scheduler defaultScheduler) { Function<? super Scheduler, ? extends Scheduler> f = onNewThreadHandler; if (f == null) { return defaultScheduler; } return apply(f, defaultScheduler); } /** * Called when a task is scheduled. * @param run the runnable instance * @return the replacement runnable */ @NonNull public static Runnable onSchedule(@NonNull Runnable run) { Objects.requireNonNull(run, "run is null"); Function<? super Runnable, ? extends Runnable> f = onScheduleHandler; if (f == null) { return run; } return apply(f, run); } /** * Calls the associated hook function. * @param defaultScheduler the hook's input value * @return the value returned by the hook */ @NonNull public static Scheduler onSingleScheduler(@NonNull Scheduler defaultScheduler) { Function<? super Scheduler, ? extends Scheduler> f = onSingleHandler; if (f == null) { return defaultScheduler; } return apply(f, defaultScheduler); } /** * Removes all handlers and resets to default behavior. */ public static void reset() { setErrorHandler(null); setScheduleHandler(null); setComputationSchedulerHandler(null); setInitComputationSchedulerHandler(null); setCachedSchedulerHandler(null); setInitCachedSchedulerHandler(null); setVirtualSchedulerHandler(null); setInitVirtualSchedulerHandler(null); setSingleSchedulerHandler(null); setInitSingleSchedulerHandler(null); setNewThreadSchedulerHandler(null); setInitNewThreadSchedulerHandler(null); setOnFlowableAssembly(null); setOnFlowableSubscribe(null); setOnObservableAssembly(null); setOnObservableSubscribe(null); setOnSingleAssembly(null); setOnSingleSubscribe(null); setOnCompletableAssembly(null); setOnCompletableSubscribe(null); setOnConnectableFlowableAssembly(null); setOnConnectableObservableAssembly(null); setOnMaybeAssembly(null); setOnMaybeSubscribe(null); setOnParallelAssembly(null); setOnParallelSubscribe(null); setOnStreamableAssembly(null); setFailOnNonBlockingScheduler(false); setOnBeforeBlocking(null); } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed */ public static void setComputationSchedulerHandler(@Nullable Function<? super Scheduler, ? extends Scheduler> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onComputationHandler = handler; } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed */ public static void setErrorHandler(@Nullable Consumer<? super Throwable> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } errorHandler = handler; } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed, but the function may not return null */ public static void setInitComputationSchedulerHandler(@Nullable Function<? super Supplier<Scheduler>, ? extends Scheduler> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onInitComputationHandler = handler; } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed, but the function may not return null */ public static void setInitCachedSchedulerHandler(@Nullable Function<? super Supplier<Scheduler>, ? extends Scheduler> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onInitCachedHandler = handler; } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed, but the function may not return null */ public static void setInitVirtualSchedulerHandler(@Nullable Function<? super Supplier<Scheduler>, ? extends Scheduler> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onInitVirtualHandler = handler; } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed, but the function may not return null */ public static void setInitNewThreadSchedulerHandler(@Nullable Function<? super Supplier<Scheduler>, ? extends Scheduler> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onInitNewThreadHandler = handler; } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed, but the function may not return null */ public static void setInitSingleSchedulerHandler(@Nullable Function<? super Supplier<Scheduler>, ? extends Scheduler> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onInitSingleHandler = handler; } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed */ public static void setCachedSchedulerHandler(@Nullable Function<? super Scheduler, ? extends Scheduler> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onCachedHandler = handler; } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed */ public static void setVirtualSchedulerHandler(@Nullable Function<? super Scheduler, ? extends Scheduler> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onVirtualHandler = handler; } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed */ public static void setNewThreadSchedulerHandler(@Nullable Function<? super Scheduler, ? extends Scheduler> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onNewThreadHandler = handler; } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed */ public static void setScheduleHandler(@Nullable Function<? super Runnable, ? extends Runnable> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onScheduleHandler = handler; } /** * Sets the specific hook function. * @param handler the hook function to set, null allowed */ public static void setSingleSchedulerHandler(@Nullable Function<? super Scheduler, ? extends Scheduler> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onSingleHandler = handler; } /** * Revokes the lockdown, only for testing purposes. */ /* test. */static void unlock() { lockdown = false; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static Function<? super Completable, ? extends Completable> getOnCompletableAssembly() { return onCompletableAssembly; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable public static BiFunction<? super Completable, @NonNull ? super CompletableObserver, @NonNull ? extends CompletableObserver> getOnCompletableSubscribe() { return onCompletableSubscribe; } /** * Returns the current hook function. * @return the hook function, may be null */ @SuppressWarnings("rawtypes") @Nullable public static Function<? super Flowable, ? extends Flowable> getOnFlowableAssembly() { return onFlowableAssembly; } /** * Returns the current hook function. * @return the hook function, may be null */ @SuppressWarnings("rawtypes") @Nullable public static Function<? super ConnectableFlowable, ? extends ConnectableFlowable> getOnConnectableFlowableAssembly() { return onConnectableFlowableAssembly; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable @SuppressWarnings("rawtypes") public static BiFunction<? super Flowable, @NonNull ? super Subscriber, @NonNull ? extends Subscriber> getOnFlowableSubscribe() { return onFlowableSubscribe; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable @SuppressWarnings("rawtypes") public static BiFunction<? super Maybe, @NonNull ? super MaybeObserver, @NonNull ? extends MaybeObserver> getOnMaybeSubscribe() { return onMaybeSubscribe; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable @SuppressWarnings("rawtypes") public static Function<? super Maybe, ? extends Maybe> getOnMaybeAssembly() { return onMaybeAssembly; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable @SuppressWarnings("rawtypes") public static Function<? super Streamable, ? extends Streamable> getOnStreamableAssembly() { return onStreamableAssembly; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable @SuppressWarnings("rawtypes") public static Function<? super Single, ? extends Single> getOnSingleAssembly() { return onSingleAssembly; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable @SuppressWarnings("rawtypes") public static BiFunction<? super Single, @NonNull ? super SingleObserver, @NonNull ? extends SingleObserver> getOnSingleSubscribe() { return onSingleSubscribe; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable @SuppressWarnings("rawtypes") public static Function<? super Observable, ? extends Observable> getOnObservableAssembly() { return onObservableAssembly; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable @SuppressWarnings("rawtypes") public static Function<? super ConnectableObservable, ? extends ConnectableObservable> getOnConnectableObservableAssembly() { return onConnectableObservableAssembly; } /** * Returns the current hook function. * @return the hook function, may be null */ @Nullable @SuppressWarnings("rawtypes") public static BiFunction<? super Observable, @NonNull ? super Observer, @NonNull ? extends Observer> getOnObservableSubscribe() { return onObservableSubscribe; } /** * Sets the specific hook function. * @param onCompletableAssembly the hook function to set, null allowed */ public static void setOnCompletableAssembly(@Nullable Function<? super Completable, ? extends Completable> onCompletableAssembly) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onCompletableAssembly = onCompletableAssembly; } /** * Sets the specific hook function. * @param onCompletableSubscribe the hook function to set, null allowed */ public static void setOnCompletableSubscribe( @Nullable BiFunction<? super Completable, @NonNull ? super CompletableObserver, @NonNull ? extends CompletableObserver> onCompletableSubscribe) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onCompletableSubscribe = onCompletableSubscribe; } /** * Sets the specific hook function. * @param onFlowableAssembly the hook function to set, null allowed */ @SuppressWarnings("rawtypes") public static void setOnFlowableAssembly(@Nullable Function<? super Flowable, ? extends Flowable> onFlowableAssembly) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onFlowableAssembly = onFlowableAssembly; } /** * Sets the specific hook function. * @param onMaybeAssembly the hook function to set, null allowed */ @SuppressWarnings("rawtypes") public static void setOnMaybeAssembly(@Nullable Function<? super Maybe, ? extends Maybe> onMaybeAssembly) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onMaybeAssembly = onMaybeAssembly; } /** * Sets the specific hook function. * @param onStreamableAssembly the hook function to set, null allowed */ @SuppressWarnings("rawtypes") public static void setOnStreamableAssembly(@Nullable Function<? super Streamable, ? extends Streamable> onStreamableAssembly) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onStreamableAssembly = onStreamableAssembly; } /** * Sets the specific hook function. * @param onConnectableFlowableAssembly the hook function to set, null allowed */ @SuppressWarnings("rawtypes") public static void setOnConnectableFlowableAssembly(@Nullable Function<? super ConnectableFlowable, ? extends ConnectableFlowable> onConnectableFlowableAssembly) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onConnectableFlowableAssembly = onConnectableFlowableAssembly; } /** * Sets the specific hook function. * @param onFlowableSubscribe the hook function to set, null allowed */ @SuppressWarnings("rawtypes") public static void setOnFlowableSubscribe(@Nullable BiFunction<? super Flowable, @NonNull ? super Subscriber, @NonNull ? extends Subscriber> onFlowableSubscribe) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onFlowableSubscribe = onFlowableSubscribe; } /** * Sets the specific hook function. * @param onMaybeSubscribe the hook function to set, null allowed */ @SuppressWarnings("rawtypes") public static void setOnMaybeSubscribe(@Nullable BiFunction<? super Maybe, @NonNull MaybeObserver, @NonNull ? extends MaybeObserver> onMaybeSubscribe) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onMaybeSubscribe = onMaybeSubscribe; } /** * Sets the specific hook function. * @param onObservableAssembly the hook function to set, null allowed */ @SuppressWarnings("rawtypes") public static void setOnObservableAssembly(@Nullable Function<? super Observable, ? extends Observable> onObservableAssembly) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onObservableAssembly = onObservableAssembly; } /** * Sets the specific hook function. * @param onConnectableObservableAssembly the hook function to set, null allowed */ @SuppressWarnings("rawtypes") public static void setOnConnectableObservableAssembly(@Nullable Function<? super ConnectableObservable, ? extends ConnectableObservable> onConnectableObservableAssembly) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onConnectableObservableAssembly = onConnectableObservableAssembly; } /** * Sets the specific hook function. * @param onObservableSubscribe the hook function to set, null allowed */ @SuppressWarnings("rawtypes") public static void setOnObservableSubscribe( @Nullable BiFunction<? super Observable, @NonNull ? super Observer, @NonNull ? extends Observer> onObservableSubscribe) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onObservableSubscribe = onObservableSubscribe; } /** * Sets the specific hook function. * @param onSingleAssembly the hook function to set, null allowed */ @SuppressWarnings("rawtypes") public static void setOnSingleAssembly(@Nullable Function<? super Single, ? extends Single> onSingleAssembly) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onSingleAssembly = onSingleAssembly; } /** * Sets the specific hook function. * @param onSingleSubscribe the hook function to set, null allowed */ @SuppressWarnings("rawtypes") public static void setOnSingleSubscribe(@Nullable BiFunction<? super Single, @NonNull ? super SingleObserver, @NonNull ? extends SingleObserver> onSingleSubscribe) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } RxJavaPlugins.onSingleSubscribe = onSingleSubscribe; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @param subscriber the subscriber * @return the value returned by the hook */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> Subscriber<? super T> onSubscribe(@NonNull Flowable<T> source, @NonNull Subscriber<? super T> subscriber) { BiFunction<? super Flowable, @NonNull ? super Subscriber, @NonNull ? extends Subscriber> f = onFlowableSubscribe; if (f != null) { return apply(f, source, subscriber); } return subscriber; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @param observer the observer * @return the value returned by the hook */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> Observer<? super T> onSubscribe(@NonNull Observable<T> source, @NonNull Observer<? super T> observer) { BiFunction<? super Observable, @NonNull ? super Observer, @NonNull ? extends Observer> f = onObservableSubscribe; if (f != null) { return apply(f, source, observer); } return observer; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @param observer the observer * @return the value returned by the hook */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> SingleObserver<? super T> onSubscribe(@NonNull Single<T> source, @NonNull SingleObserver<? super T> observer) { BiFunction<? super Single, @NonNull ? super SingleObserver, @NonNull ? extends SingleObserver> f = onSingleSubscribe; if (f != null) { return apply(f, source, observer); } return observer; } /** * Calls the associated hook function. * @param source the hook's input value * @param observer the observer * @return the value returned by the hook */ @NonNull public static CompletableObserver onSubscribe(@NonNull Completable source, @NonNull CompletableObserver observer) { BiFunction<? super Completable, @NonNull ? super CompletableObserver, @NonNull ? extends CompletableObserver> f = onCompletableSubscribe; if (f != null) { return apply(f, source, observer); } return observer; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @param observer the subscriber * @return the value returned by the hook */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> MaybeObserver<? super T> onSubscribe(@NonNull Maybe<T> source, @NonNull MaybeObserver<? super T> observer) { BiFunction<? super Maybe, @NonNull ? super MaybeObserver, @NonNull ? extends MaybeObserver> f = onMaybeSubscribe; if (f != null) { return apply(f, source, observer); } return observer; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @param subscribers the array of subscribers * @return the value returned by the hook */ @SuppressWarnings({ "unchecked" }) @NonNull public static <@NonNull T> Subscriber<? super T>[] onSubscribe(@NonNull ParallelFlowable<? extends T> source, @NonNull Subscriber<? super T>[] subscribers) { var f = onParallelSubscribe; if (f != null) { return (@NonNull Subscriber<@NonNull ? super @NonNull T>[]) apply(f, source, subscribers); } return subscribers; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @return the value returned by the hook */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> Maybe<T> onAssembly(@NonNull Maybe<T> source) { Function<? super Maybe, ? extends Maybe> f = onMaybeAssembly; if (f != null) { return apply(f, source); } return source; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @return the value returned by the hook */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> Flowable<T> onAssembly(@NonNull Flowable<T> source) { Function<? super Flowable, ? extends Flowable> f = onFlowableAssembly; if (f != null) { return apply(f, source); } return source; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @return the value returned by the hook */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> Streamable<T> onAssembly(@NonNull Streamable<T> source) { Function<? super Streamable, ? extends Streamable> f = onStreamableAssembly; if (f != null) { return apply(f, source); } return source; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @return the value returned by the hook */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> ConnectableFlowable<T> onAssembly(@NonNull ConnectableFlowable<T> source) { Function<? super ConnectableFlowable, ? extends ConnectableFlowable> f = onConnectableFlowableAssembly; if (f != null) { return apply(f, source); } return source; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @return the value returned by the hook */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> Observable<T> onAssembly(@NonNull Observable<T> source) { Function<? super Observable, ? extends Observable> f = onObservableAssembly; if (f != null) { return apply(f, source); } return source; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @return the value returned by the hook */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> ConnectableObservable<T> onAssembly(@NonNull ConnectableObservable<T> source) { Function<? super ConnectableObservable, ? extends ConnectableObservable> f = onConnectableObservableAssembly; if (f != null) { return apply(f, source); } return source; } /** * Calls the associated hook function. * @param <T> the value type * @param source the hook's input value * @return the value returned by the hook */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> Single<T> onAssembly(@NonNull Single<T> source) { Function<? super Single, ? extends Single> f = onSingleAssembly; if (f != null) { return apply(f, source); } return source; } /** * Calls the associated hook function. * @param source the hook's input value * @return the value returned by the hook */ @NonNull public static Completable onAssembly(@NonNull Completable source) { Function<? super Completable, ? extends Completable> f = onCompletableAssembly; if (f != null) { return apply(f, source); } return source; } /** * Sets the specific hook function. * <p>History: 2.0.6 - experimental; 2.1 - beta * @param handler the hook function to set, null allowed * @since 2.2 */ @SuppressWarnings("rawtypes") public static void setOnParallelAssembly(@Nullable Function<? super ParallelFlowable, ? extends ParallelFlowable> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onParallelAssembly = handler; } /** * Returns the current hook function. * <p>History: 2.0.6 - experimental; 2.1 - beta * @return the hook function, may be null * @since 2.2 */ @SuppressWarnings("rawtypes") @Nullable public static Function<? super ParallelFlowable, ? extends ParallelFlowable> getOnParallelAssembly() { return onParallelAssembly; } /** * Sets the specific hook function. * <p>History: 3.0.11 - experimental * @param handler the hook function to set, null allowed * @since 3.1.0 */ @SuppressWarnings("rawtypes") public static void setOnParallelSubscribe(@Nullable BiFunction<? super ParallelFlowable, @NonNull ? super Subscriber<@NonNull ?>[], @NonNull ? extends Subscriber<@NonNull ?>[]> handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onParallelSubscribe = handler; } /** * Returns the current hook function. * <p>History: 3.0.11 - experimental * @return the hook function, may be null * @since 3.1.0 */ @SuppressWarnings("rawtypes") @Nullable public static BiFunction<? super ParallelFlowable, @NonNull ? super Subscriber<@NonNull ?>[], @NonNull ? extends Subscriber<@NonNull ?>[]> getOnParallelSubscribe() { return onParallelSubscribe; } /** * Calls the associated hook function. * <p>History: 2.0.6 - experimental; 2.1 - beta * @param <T> the value type of the source * @param source the hook's input value * @return the value returned by the hook * @since 2.2 */ @SuppressWarnings({ "rawtypes", "unchecked" }) @NonNull public static <@NonNull T> ParallelFlowable<T> onAssembly(@NonNull ParallelFlowable<T> source) { Function<? super ParallelFlowable, ? extends ParallelFlowable> f = onParallelAssembly; if (f != null) { return apply(f, source); } return source; } /** * Called before an operator attempts a blocking operation * such as awaiting a condition or signal * and should return true to indicate the operator * should not block but throw an IllegalArgumentException. * <p>History: 2.0.5 - experimental * @return true if the blocking should be prevented * @see #setFailOnNonBlockingScheduler(boolean) * @since 2.1 */ public static boolean onBeforeBlocking() { BooleanSupplier f = onBeforeBlocking; if (f != null) { try { return f.getAsBoolean(); } catch (Throwable ex) { throw ExceptionHelper.wrapOrThrow(ex); } } return false; } /** * Set the handler that is called when an operator attempts a blocking * await; the handler should return true to prevent the blocking * and to signal an IllegalStateException instead. * <p>History: 2.0.5 - experimental * @param handler the handler to set, null resets to the default handler * that always returns false * @see #onBeforeBlocking() * @since 2.1 */ public static void setOnBeforeBlocking(@Nullable BooleanSupplier handler) { if (lockdown) { throw new IllegalStateException("Plugins can't be changed anymore"); } onBeforeBlocking = handler; } /** * Returns the current blocking handler or null if no custom handler * is set. * <p>History: 2.0.5 - experimental * @return the current blocking handler or null if not specified * @since 2.1 */ @Nullable public static BooleanSupplier getOnBeforeBlocking() { return onBeforeBlocking; } /** * Create an instance of the default {@link Scheduler} used for {@link Schedulers#computation()} * except using {@code threadFactory} for thread creation. * <p>History: 2.0.5 - experimental * @param threadFactory thread factory to use for creating worker threads. Note that this takes precedence over any * system properties for configuring new thread creation. Cannot be null. * @return the created Scheduler instance * @since 2.1 */ @NonNull public static Scheduler createComputationScheduler(@NonNull ThreadFactory threadFactory) { return new ComputationScheduler(Objects.requireNonNull(threadFactory, "threadFactory is null")); } /** * Create an instance of the default {@link Scheduler} used for {@link Schedulers#cached()} * except using {@code threadFactory} for thread creation. * <p>History: 2.0.5 - experimental * @param threadFactory thread factory to use for creating worker threads. Note that this takes precedence over any * system properties for configuring new thread creation. Cannot be null. * @return the created Scheduler instance * @since 4.0.0 */ @NonNull public static Scheduler createCachedScheduler(@NonNull ThreadFactory threadFactory) { return new CachedScheduler(Objects.requireNonNull(threadFactory, "threadFactory is null")); } /** * Create an instance of the default {@link Scheduler} used for {@link Schedulers#newThread()} * except using {@code threadFactory} for thread creation. * <p>History: 2.0.5 - experimental * @param threadFactory thread factory to use for creating worker threads. Note that this takes precedence over any * system properties for configuring new thread creation. Cannot be null. * @return the created Scheduler instance * @since 2.1 */ @NonNull public static Scheduler createNewThreadScheduler(@NonNull ThreadFactory threadFactory) { return new NewThreadScheduler(Objects.requireNonNull(threadFactory, "threadFactory is null")); } /** * Create an instance of the default {@link Scheduler} used for {@link Schedulers#single()} * except using {@code threadFactory} for thread creation. * <p>History: 2.0.5 - experimental * @param threadFactory thread factory to use for creating worker threads. Note that this takes precedence over any * system properties for configuring new thread creation. Cannot be null. * @return the created Scheduler instance * @since 2.1 */ @NonNull public static Scheduler createSingleScheduler(@NonNull ThreadFactory threadFactory) { return new SingleScheduler(Objects.requireNonNull(threadFactory, "threadFactory is null")); } /** * Create an instance of a {@link Scheduler} by wrapping an existing {@link Executor}. * <p> * This method allows creating an {@code Executor}-backed {@code Scheduler} before the {@link Schedulers} class * would initialize the standard {@code Scheduler}s. * * @param executor the {@code Executor} to wrap and turn into a {@code Scheduler}. * @param interruptibleWorker if {@code true}, the tasks submitted to the {@link io.reactivex.rxjava4.core.Scheduler.Worker Scheduler.Worker} will * be interrupted when the task is disposed. * @param fair if {@code true}, tasks submitted to the {@code Scheduler} or {@code Worker} will be executed by the underlying {@code Executor} one after the other, still * in a FIFO and non-overlapping manner, but allows interleaving with other tasks submitted to the underlying {@code Executor}. * If {@code false}, the underlying FIFO scheme will execute as many tasks as it can before giving up the underlying {@code Executor} thread. * @return the new {@code Scheduler} wrapping the {@code Executor} * @since 3.1.0 */ @NonNull public static Scheduler createExecutorScheduler(@NonNull Executor executor, boolean interruptibleWorker, boolean fair) { return new ExecutorScheduler(executor, interruptibleWorker, fair); } /** * Create an instance of a {@link Scheduler} by wrapping a supplier of a {@link Executor}. * <p> * This method allows creating a deferred {@code Executor}-backed {@code Scheduler} before the {@link Schedulers} class * would initialize the standard {@code Scheduler}s. * * @param executorSupplier the {@code Executor} supplier to wrap and turn into a {@code Scheduler}. * @param interruptibleWorker if {@code true}, the tasks submitted to the {@link io.reactivex.rxjava4.core.Scheduler.Worker Scheduler.Worker} will * be interrupted when the task is disposed. * @param fair if {@code true}, tasks submitted to the {@code Scheduler} or {@code Worker} will be executed by the underlying {@code Executor} one after the other, still * in a FIFO and non-overlapping manner, but allows interleaving with other tasks submitted to the underlying {@code Executor}. * If {@code false}, the underlying FIFO scheme will execute as many tasks as it can before giving up the underlying {@code Executor} thread. * @return the new {@code Scheduler} wrapping the {@code Executor} * @since 4.0.0 */ @NonNull public static Scheduler createDeferredExecutorScheduler(@NonNull Supplier<? extends Executor> executorSupplier, boolean interruptibleWorker, boolean fair) { return new DeferredExecutorScheduler(executorSupplier, interruptibleWorker, fair); } /** * Wraps the call to the function in try-catch and propagates thrown * checked exceptions as RuntimeException. * @param <T> the input type * @param <R> the output type * @param f the function to call, not null (not verified) * @param t the parameter value to the function * @return the result of the function call */ @NonNull static <@NonNull T, @NonNull R> R apply(@NonNull Function<T, R> f, @NonNull T t) { try { return f.apply(t); } catch (Throwable ex) { throw ExceptionHelper.wrapOrThrow(ex); } } /** * Wraps the call to the function in try-catch and propagates thrown * checked exceptions as RuntimeException. * @param <T> the first input type * @param <U> the second input type * @param <R> the output type * @param f the function to call, not null (not verified) * @param t the first parameter value to the function * @param u the second parameter value to the function * @return the result of the function call */ @NonNull static <@NonNull T, @NonNull U, @NonNull R> R apply(@NonNull BiFunction<? super T, ? super U, ? extends R> f, @NonNull T t, @NonNull U u) { try { return f.apply(t, u); } catch (Throwable ex) { throw ExceptionHelper.wrapOrThrow(ex); } } /** * Wraps the call to the Scheduler creation supplier in try-catch and propagates thrown * checked exceptions as RuntimeException and enforces that result is not null. * @param s the {@link Supplier} which returns a {@link Scheduler}, not null (not verified). Cannot return null * @return the result of the supplier call, not null * @throws NullPointerException if the supplier parameter returns null */ @NonNull static Scheduler callRequireNonNull(@NonNull Supplier<Scheduler> s) { try { return Objects.requireNonNull(s.get(), "Scheduler Supplier result can't be null"); } catch (Throwable ex) { throw ExceptionHelper.wrapOrThrow(ex); } } /** * Wraps the call to the Scheduler creation function in try-catch and propagates thrown * checked exceptions as RuntimeException and enforces that result is not null. * @param f the function to call, not null (not verified). Cannot return null * @param s the parameter value to the function * @return the result of the function call, not null * @throws NullPointerException if the function parameter returns null */ @NonNull static Scheduler applyRequireNonNull(@NonNull Function<? super Supplier<Scheduler>, ? extends Scheduler> f, Supplier<Scheduler> s) { return Objects.requireNonNull(apply(f, s), "Scheduler Supplier result can't be null"); } /** Helper class, no instances. */ private RxJavaPlugins() { throw new IllegalStateException("No instances!"); } }