Class Ui
UiRuntime, Limn's first-class
async API. The backend installs the runtime at startup; application code
then uses:
button.onAction(() ->
Ui.async(() -> repository.load()) // worker pool
.thenAccept(data -> label.setText(data)) // back on the UI thread
);
Thread confinement is a hard rule: every widget mutation calls
checkUiThread() and throws IllegalStateException when
violated.
-
Method Summary
Modifier and TypeMethodDescriptionstatic <T extends @Nullable Object>
CompletionStage<T> Runsworkon the worker pool; the returned stage completes on the UI thread (including its default async executor).static voidstatic Executorexecutor()static voidInstalls the process-wide runtime.static booleanstatic booleanstatic voidRunsactionon the UI thread on the next frame.static SubscriptionpostDelayed(Runnable action, long delayMillis) Runsactionon the UI thread afterdelayMillis.static voidUninstallscandidateif it is the installed runtime (backend shutdown).Describes background work with a lifecycle: cancellable, able to report progress, and able to decline delivery when whoever asked has gone away.
-
Method Details
-
install
Installs the process-wide runtime. Called by the backend once at startup.- Throws:
IllegalStateException- if a different runtime is already installed
-
uninstall
Uninstallscandidateif it is the installed runtime (backend shutdown). The shared loads of images and sounds are forgotten with it: one still in flight would complete on this runtime's queue, which nothing drains any more, and a later backend asking for the same file would be handed a future that never completes. And what the application left open that keeps a thread for as long as it is open, a media player, is closed first, while there is still a UI thread to close it on. -
isInstalled
public static boolean isInstalled()- Returns:
- whether a runtime is installed (i.e. a Backend is running)
-
post
Runsactionon the UI thread on the next frame. Any-thread safe.A task that mutates widget or scene state is responsible for invalidating what it touched:
Widget.invalidate(),Widget.markNeedsLayout()orScene.requestRender(). Running a task buys no frame of its own, so a mutation nothing invalidates stays unpainted until something else asks for one. Every widget setter and every tree change invalidates already; a task that writes a field behind a setter's back, or that changes what a customonPaintreads, does not. -
postDelayed
Runsactionon the UI thread afterdelayMillis. Any-thread safe.A task that mutates widget or scene state is responsible for invalidating what it touched: see
post(java.lang.Runnable). Firing buys no frame of its own, which is what makes a timer the cheap way to watch something that rarely changes: a poll that re-reads a value and finds it unchanged costs a wake-up and nothing else, where atickerasks for a frame every frame it stays registered.- Returns:
- a handle that withdraws the task if it has not run; cancelling it afterwards, or twice, does nothing. Any thread. Whoever arms a timer for something that can go away first, a widget or a window, cancels it there: a task waiting holds all it captures until it runs
-
async
Runsworkon the worker pool; the returned stage completes on the UI thread (including its default async executor).A dependent that mutates widget or scene state is responsible for invalidating what it touched: see
post(java.lang.Runnable). Completing on the UI thread buys no frame;label.setText(data)asks for the frame that shows it, a field written directly does not. -
work
Describes background work with a lifecycle: cancellable, able to report progress, and able to decline delivery when whoever asked has gone away. Nothing runs untilWork.start():job = Ui.work(progress -> repository.search(term)) .onSuccess(results::setItems) .deliverIf(results::isShowing) .start();Reach for this over
async(java.util.function.Supplier<T>)whenever the request can be superseded: cancelling the previous job means the view shows the answer to the question last asked, rather than whichever answer happened to finish last. -
isUiThread
public static boolean isUiThread()- Returns:
trueiff called on the UI thread (false when no runtime is installed)
-
checkUiThread
public static void checkUiThread()- Throws:
IllegalStateException- if not on the UI thread (or no runtime installed)
-
executor
- Returns:
- an executor that posts to the UI thread
-