-
public final class ThreadingKt
-
-
Method Summary
Modifier and Type Method Description final static <T extends Any> Result<T>runOnMainLooper(Function0<T> block)Executes the given block on the main (UI) thread and returns the result. final static <T extends Any> Result<T>runOn(Looper looper, Function0<T> block)Executes the given block on the specified looper's thread and returns the result. -
-
Method Detail
-
runOnMainLooper
final static <T extends Any> Result<T> runOnMainLooper(Function0<T> block)
Executes the given block on the main (UI) thread and returns the result.
This function provides thread-safe access to the main looper with proper synchronization:
If already on the main thread, executes block immediately
If on a different thread, posts to the main looper and blocks the caller until completion
Returns a Result that captures success values or exceptions from block
This function is blocking for the calling thread when switching threads. It uses a CountDownLatch to wait for the main thread to complete execution before returning.
If the main thread does not execute block within 5 seconds, this function throws IllegalStateException. This prevents indefinite blocking if the main thread is stuck.
Exceptions thrown by block are captured and returned as
Result.failurekotlin.coroutines.cancellation.CancellationException is rethrown to preserve coroutine cancellation semantics
If the main looper is not initialized, throws IllegalStateException
Updating UI components from background threads
Adding/removing lifecycle observers (requires main thread)
Accessing View properties that must be read on the main thread
Synchronizing with main thread state before proceeding
// From a background thread, safely add a lifecycle observer runOnMainLooper { lifecycle.addObserver(observer) }.onFailure { error -> logger.e(error) { "Failed to add lifecycle observer" } } // Get a value from the UI thread val result = runOnMainLooper { view.width }.getOrNull() // Execute multiple UI operations atomically runOnMainLooper { textView.text = "Loading..." progressBar.visibility = View.VISIBLE }- Parameters:
block- the code to execute on the main thread
-
runOn
final static <T extends Any> Result<T> runOn(Looper looper, Function0<T> block)
Executes the given block on the specified looper's thread and returns the result.
This is a generalized version of runOnMainLooper that works with any Looper:
If already on the target looper's thread, executes block immediately
If on a different thread, posts to the target looper and blocks the caller until completion
Returns a Result that captures success values or exceptions from block
This function is blocking for the calling thread when switching threads. It uses a CountDownLatch to wait for the target looper's thread to complete execution before returning.
If the target looper does not execute block within 5 seconds, this function throws IllegalStateException. This prevents indefinite blocking if the target thread is stuck or the looper is not running.
Exceptions thrown by block are captured and returned as
Result.failurekotlin.coroutines.cancellation.CancellationException is rethrown to preserve coroutine cancellation semantics
Executing code on a custom HandlerThread's looper
Synchronizing operations across multiple threads with known loopers
Testing thread-specific behavior with custom test loopers
// Execute on a custom background thread val handlerThread = HandlerThread("worker").apply { start() } val workerLooper = handlerThread.looper runOn(workerLooper) { // This code runs on the worker thread performExpensiveOperation() }.onSuccess { result -> println("Operation completed with result: $result") } // Verify we're on the correct thread val isCorrectThread = runOn(targetLooper) { Looper.myLooper() == targetLooper }.getOrDefault(false) // Chain thread operations runOn(backgroundLooper) { val data = fetchData() runOnMainLooper { updateUI(data) } }When already on the target looper's thread, there is minimal overhead (just a looper check)
When switching threads, the calling thread blocks until execution completes
Consider using coroutines with appropriate dispatchers for non-blocking alternatives
- Parameters:
looper- the Looper on whose thread to execute blockblock- the code to execute on the looper's thread
-
-
-
-