Add uiThreadConditionalSync executor to AndroidExecutors

Summary:
Changelog: [internal]

This adds a new type of executor in AndroidExecutors to execute runnables on the UI thread.

If the caller is already on the UI thread it'd call the runnable immediately. Otherwise it'd be scheduled in the UI thread to execute asynchronously.

Reviewed By: huntie

Differential Revision: D53941120

fbshipit-source-id: b68c7a4540be2a12df930e4e52eeb7b7a1aa91d8
This commit is contained in:
Rubén Norte
2024-02-28 09:53:18 -08:00
committed by Facebook GitHub Bot
parent eff28ae113
commit a861a66d71
3 changed files with 46 additions and 3 deletions
@@ -3673,6 +3673,7 @@ public abstract interface class com/facebook/react/runtime/internal/bolts/Contin
public class com/facebook/react/runtime/internal/bolts/Task : com/facebook/react/interfaces/TaskInterface {
public static final field BACKGROUND_EXECUTOR Ljava/util/concurrent/ExecutorService;
public static final field UI_THREAD_CONDITIONAL_SYNC_EXECUTOR Ljava/util/concurrent/Executor;
public static final field UI_THREAD_EXECUTOR Ljava/util/concurrent/Executor;
public static fun call (Ljava/util/concurrent/Callable;)Lcom/facebook/react/runtime/internal/bolts/Task;
public static fun call (Ljava/util/concurrent/Callable;Lcom/facebook/react/runtime/internal/bolts/CancellationToken;)Lcom/facebook/react/runtime/internal/bolts/Task;
@@ -39,9 +39,11 @@ final class AndroidExecutors {
private static final AndroidExecutors INSTANCE = new AndroidExecutors();
@NonNull private final Executor uiThread;
@NonNull private final Executor uiThreadConditionalSync;
private AndroidExecutors() {
uiThread = new UIThreadExecutor();
uiThreadConditionalSync = new UIThreadConditionalSyncExecutor();
}
/**
@@ -122,16 +124,52 @@ final class AndroidExecutors {
}
}
/** An {@link java.util.concurrent.Executor} that executes tasks on the UI thread. */
/**
* An {@link java.util.concurrent.Executor} that schedules tasks to run asynchronously on the UI
* thread.
*/
public static @NonNull Executor uiThread() {
return INSTANCE.uiThread;
}
/** An {@link java.util.concurrent.Executor} that runs tasks on the UI thread. */
/**
* An {@link java.util.concurrent.Executor} that runs tasks on the UI thread (immediately if
* already on that thread).
*/
public static @NonNull Executor uiThreadConditionalSync() {
return INSTANCE.uiThreadConditionalSync;
}
/**
* An {@link java.util.concurrent.Executor} that schedules tasks to run asynchronously on the UI
* thread.
*/
private static class UIThreadExecutor implements Executor {
private final Handler mHandler = new Handler(Looper.getMainLooper());
@Override
public void execute(@NonNull Runnable command) {
new Handler(Looper.getMainLooper()).post(command);
// Otherwise, post it on the main thread handler
mHandler.post(command);
}
}
/**
* An {@link java.util.concurrent.Executor} that runs tasks on the UI thread (immediately if
* already on that thread).
*/
private static class UIThreadConditionalSyncExecutor implements Executor {
private final Handler mHandler = new Handler(Looper.getMainLooper());
@Override
public void execute(@NonNull Runnable command) {
if (Looper.myLooper() == mHandler.getLooper()) {
// If we're already on the main thread, execute the command immediately
command.run();
} else {
// Otherwise, post it on the main thread handler
mHandler.post(command);
}
}
}
}
@@ -42,6 +42,10 @@ public class Task<TResult> implements TaskInterface<TResult> {
/** An {@link java.util.concurrent.Executor} that executes tasks on the UI thread. */
public static final Executor UI_THREAD_EXECUTOR = AndroidExecutors.uiThread();
/** An {@link java.util.concurrent.Executor} that executes tasks on the UI thread. */
public static final Executor UI_THREAD_CONDITIONAL_SYNC_EXECUTOR =
AndroidExecutors.uiThreadConditionalSync();
/**
* Interface for handlers invoked when a failed {@code Task} is about to be finalized, but the
* exception has not been consumed.