CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-compose-ui--ui-uikitsimarm64

Compose Multiplatform UI library for iOS Simulator ARM64 target providing declarative UI framework based on Jetpack Compose for multiplatform development

Pending
Overview
Eval results
Files

state.mddocs/

State Management

State handling and lifecycle management for reactive UI updates and side effects in Compose applications, enabling dynamic and interactive user interfaces.

Capabilities

Core State APIs

Fundamental state management functions for creating and managing reactive state in Compose applications.

/**
 * Remember a value across recompositions.
 */
@Composable
fun <T> remember(calculation: () -> T): T

/**
 * Remember a value with a single key for cache invalidation.
 */
@Composable
fun <T> remember(
    key1: Any?,
    calculation: () -> T
): T

/**
 * Remember a value with two keys for cache invalidation.
 */
@Composable
fun <T> remember(
    key1: Any?,
    key2: Any?,
    calculation: () -> T
): T

/**
 * Remember a value with three keys for cache invalidation.
 */
@Composable
fun <T> remember(
    key1: Any?,
    key2: Any?,
    key3: Any?,
    calculation: () -> T
): T

/**
 * Remember a value with arbitrary keys for cache invalidation.
 */
@Composable
fun <T> remember(
    vararg keys: Any?,
    calculation: () -> T
): T

/**
 * Create a mutable state holder with structural equality policy.
 */
fun <T> mutableStateOf(
    value: T,
    policy: SnapshotMutationPolicy<T> = structuralEqualityPolicy()
): MutableState<T>

/**
 * Create a mutable state holder with referential equality policy.
 */
fun <T> mutableStateOf(
    value: T,
    policy: SnapshotMutationPolicy<T> = referentialEqualityPolicy()
): MutableState<T>

/**
 * A state holder that represents a value and allows observation of changes.
 */
interface State<out T> {
    val value: T
}

/**
 * A mutable state holder that can be read and written.
 */
interface MutableState<T> : State<T> {
    override var value: T
    operator fun component1(): T
    operator fun component2(): (T) -> Unit
}

/**
 * Create a derived state that is calculated from other state values.
 */
@Composable
fun <T> derivedStateOf(calculation: () -> T): State<T>

/**
 * Mutation policies for state management.
 */
fun <T> structuralEqualityPolicy(): SnapshotMutationPolicy<T>
fun <T> referentialEqualityPolicy(): SnapshotMutationPolicy<T>
fun <T> neverEqualPolicy(): SnapshotMutationPolicy<T>

/**
 * Policy for determining when state changes trigger recomposition.
 */
interface SnapshotMutationPolicy<T> {
    fun equivalent(a: T, b: T): Boolean
    fun merge(previous: T, current: T, applied: T): T?
}

Usage Examples:

// Basic state management
@Composable
fun StateExample() {
    // Simple state with remember and mutableStateOf
    var count by remember { mutableStateOf(0) }
    var text by remember { mutableStateOf("") }
    
    Column(
        modifier = Modifier.padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp)
    ) {
        Text("Count: $count")
        
        Row {
            Button(onClick = { count++ }) {
                Text("Increment")
            }
            Button(onClick = { count-- }) {
                Text("Decrement")
            }
            Button(onClick = { count = 0 }) {
                Text("Reset")
            }
        }
        
        TextField(
            value = text,
            onValueChange = { text = it },
            label = { Text("Enter text") }
        )
        
        Text("Text length: ${text.length}")
    }
}

// Derived state example
@Composable
fun DerivedStateExample() {
    var firstName by remember { mutableStateOf("") }
    var lastName by remember { mutableStateOf("") }
    
    // Derived state that recalculates when firstName or lastName changes
    val fullName by derivedStateOf { 
        "$firstName $lastName".trim()
    }
    
    Column(modifier = Modifier.padding(16.dp)) {
        TextField(
            value = firstName,
            onValueChange = { firstName = it },
            label = { Text("First Name") }
        )
        
        TextField(
            value = lastName,
            onValueChange = { lastName = it },
            label = { Text("Last Name") }
        )
        
        Text("Full Name: $fullName")
        Text("Name is ${if (fullName.isNotEmpty()) "not " else ""}empty")
    }
}

// State with keys for cache invalidation
@Composable
fun KeyedStateExample(userId: String) {
    // State that resets when userId changes
    var userPreferences by remember(userId) {
        mutableStateOf(loadUserPreferences(userId))
    }
    
    // Expensive calculation that only recalculates when specific values change
    val processedData by remember(userPreferences.theme, userPreferences.language) {
        derivedStateOf {
            processUserData(userPreferences.theme, userPreferences.language)
        }
    }
    
    // UI using the state...
}

fun loadUserPreferences(userId: String): UserPreferences = TODO()
fun processUserData(theme: String, language: String): ProcessedData = TODO()

Side Effects

System for performing side effects and managing lifecycle in Compose applications.

/**
 * Launch a coroutine tied to the composition lifecycle.
 */
@Composable
fun LaunchedEffect(
    key1: Any?,
    block: suspend CoroutineScope.() -> Unit
)

/**
 * Launch a coroutine with multiple keys.
 */
@Composable
fun LaunchedEffect(
    key1: Any?,
    key2: Any?,
    block: suspend CoroutineScope.() -> Unit
)

/**
 * Launch a coroutine with arbitrary keys.
 */
@Composable
fun LaunchedEffect(
    vararg keys: Any?,
    block: suspend CoroutineScope.() -> Unit
)

/**
 * Create and remember a coroutine scope tied to the composition.
 */
@Composable
fun rememberCoroutineScope(): CoroutineScope

/**
 * Create a disposable effect that cleans up when keys change or composition exits.
 */
@Composable
fun DisposableEffect(
    key1: Any?,
    effect: DisposableEffectScope.() -> DisposableEffectResult
)

/**
 * Create a disposable effect with multiple keys.
 */
@Composable
fun DisposableEffect(
    key1: Any?,
    key2: Any?,
    effect: DisposableEffectScope.() -> DisposableEffectResult
)

/**
 * Create a disposable effect with arbitrary keys.
 */
@Composable
fun DisposableEffect(
    vararg keys: Any?,
    effect: DisposableEffectScope.() -> DisposableEffectResult
)

/**
 * Scope for disposable effects.
 */
interface DisposableEffectScope {
    /**
     * Create a disposal callback.
     */
    fun onDispose(onDisposeEffect: () -> Unit): DisposableEffectResult
}

/**
 * Result of a disposable effect.
 */
interface DisposableEffectResult

/**
 * Create a side effect that runs after every recomposition.
 */
@Composable
fun SideEffect(effect: () -> Unit)

Usage Examples:

// LaunchedEffect for one-time or key-dependent side effects
@Composable
fun LaunchedEffectExample(userId: String) {
    var userData by remember { mutableStateOf<UserData?>(null) }
    var isLoading by remember { mutableStateOf(false) }
    var error by remember { mutableStateOf<String?>(null) }
    
    // Launch effect when userId changes
    LaunchedEffect(userId) {
        isLoading = true
        error = null
        try {
            userData = fetchUserData(userId)
        } catch (e: Exception) {
            error = e.message
        } finally {
            isLoading = false
        }
    }
    
    // One-time effect (runs only once)
    LaunchedEffect(Unit) {
        // Initialize analytics, start location updates, etc.
        initializeApp()
    }
    
    when {
        isLoading -> Text("Loading...")
        error != null -> Text("Error: $error", color = Color.Red)
        userData != null -> UserDataDisplay(userData!!)
        else -> Text("No data")
    }
}

// DisposableEffect for cleanup
@Composable
fun DisposableEffectExample() {
    val lifecycleOwner = LocalLifecycleOwner.current
    
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            when (event) {
                Lifecycle.Event.ON_START -> {
                    // Start location updates, register listeners, etc.
                }
                Lifecycle.Event.ON_STOP -> {
                    // Stop location updates, unregister listeners, etc.
                }
                else -> {}
            }
        }
        
        lifecycleOwner.lifecycle.addObserver(observer)
        
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }
}

// RememberCoroutineScope for event-driven coroutines
@Composable
fun CoroutineScopeExample() {
    val scope = rememberCoroutineScope()
    var result by remember { mutableStateOf("") }
    
    Column {
        Button(onClick = {
            scope.launch {
                result = "Loading..."
                try {
                    delay(2000) // Simulate network call
                    result = "Data loaded successfully!"
                } catch (e: Exception) {
                    result = "Error: ${e.message}"
                }
            }
        }) {
            Text("Load Data")
        }
        
        Text(result)
    }
}

// SideEffect for non-compose state synchronization
@Composable
fun SideEffectExample(value: String) {
    // Update external system whenever value changes
    SideEffect {
        // This runs after every recomposition where value might have changed
        updateExternalSystem(value)
    }
}

suspend fun fetchUserData(userId: String): UserData = TODO()
fun initializeApp() = TODO()
fun updateExternalSystem(value: String) = TODO()

State Persistence

System for persisting state across configuration changes and app restarts.

/**
 * Remember a value that survives configuration changes.
 */
@Composable
fun <T : Any> rememberSaveable(
    vararg inputs: Any?,
    saver: Saver<T, out Any> = autoSaver(),
    key: String? = null,
    init: () -> T
): T

/**
 * Remember a mutable state that survives configuration changes.
 */
@Composable
fun <T : Any> rememberSaveable(
    vararg inputs: Any?,
    stateSaver: Saver<T, out Any> = autoSaver(),
    key: String? = null,
    init: () -> MutableState<T>
): MutableState<T>

/**
 * Interface for saving and restoring state.
 */
interface Saver<Original, Saveable : Any> {
    fun save(value: Original): Saveable?
    fun restore(value: Saveable): Original?
}

/**
 * Create a Saver using save and restore functions.
 */
fun <Original, Saveable : Any> Saver(
    save: (value: Original) -> Saveable?,
    restore: (value: Saveable) -> Original?
): Saver<Original, Saveable>

/**
 * Create a list saver for collections.
 */
fun <Original, Saveable : Any> listSaver(
    save: (value: Original) -> List<Saveable>,
    restore: (list: List<Saveable>) -> Original?
): Saver<Original, Any>

/**
 * Create a map saver for complex objects.
 */
fun <T : Any> mapSaver(
    save: (value: T) -> Map<String, Any?>,
    restore: (map: Map<String, Any?>) -> T?
): Saver<T, Any>

/**
 * Automatic saver that works with basic types.
 */
fun <T> autoSaver(): Saver<T, Any>

Usage Examples:

// Basic saveable state
@Composable
fun SaveableStateExample() {
    // This state survives configuration changes
    var count by rememberSaveable { mutableStateOf(0) }
    var text by rememberSaveable { mutableStateOf("") }
    
    Column {
        Text("Count: $count (survives rotation)")
        Button(onClick = { count++ }) {
            Text("Increment")
        }
        
        TextField(
            value = text,
            onValueChange = { text = it },
            label = { Text("Persistent text") }
        )
    }
}

// Custom saver for complex objects
data class UserProfile(
    val name: String,
    val email: String,
    val age: Int
)

val UserProfileSaver = Saver<UserProfile, Map<String, Any>>(
    save = { profile ->
        mapOf(
            "name" to profile.name,
            "email" to profile.email,
            "age" to profile.age
        )
    },
    restore = { map ->
        UserProfile(
            name = map["name"] as String,
            email = map["email"] as String,
            age = map["age"] as Int
        )
    }
)

@Composable
fun CustomSaverExample() {
    var userProfile by rememberSaveable(saver = UserProfileSaver) {
        mutableStateOf(UserProfile("", "", 0))
    }
    
    Column {
        TextField(
            value = userProfile.name,
            onValueChange = { userProfile = userProfile.copy(name = it) },
            label = { Text("Name") }
        )
        
        TextField(
            value = userProfile.email,
            onValueChange = { userProfile = userProfile.copy(email = it) },
            label = { Text("Email") }
        )
        
        // Age input field...
    }
}

// List saver example
val IntListSaver = listSaver<List<Int>, Int>(
    save = { it },
    restore = { it }
)

@Composable
fun ListSaverExample() {
    var numbers by rememberSaveable(saver = IntListSaver) {
        mutableStateOf(listOf<Int>())
    }
    
    Column {
        Button(onClick = { 
            numbers = numbers + (numbers.size + 1)
        }) {
            Text("Add Number")
        }
        
        LazyColumn {
            items(numbers) { number ->
                Text("Number: $number")
            }
        }
    }
}

State Hoisting

Patterns for managing state in larger component hierarchies and sharing state between components.

/**
 * Snapshot state management for batch updates.
 */
object Snapshot {
    /**
     * Take a snapshot of the current state.
     */
    fun takeSnapshot(readObserver: ((Any) -> Unit)? = null): Snapshot
    
    /**
     * Send and apply all changes in a snapshot.
     */
    fun sendApplyNotifications()
    
    /**
     * Create a mutable snapshot for making changes.
     */
    fun takeMutableSnapshot(
        readObserver: ((Any) -> Unit)? = null,
        writeObserver: ((Any) -> Unit)? = null
    ): MutableSnapshot
    
    /**
     * Observe state reads within a block.
     */
    fun <T> observe(
        readObserver: ((Any) -> Unit)?,
        writeObserver: ((Any) -> Unit)? = null,
        block: () -> T
    ): T
    
    /**
     * Run a block without triggering state reads.
     */
    fun <T> withoutReadObservation(block: () -> T): T
    
    /**
     * Run a block with all mutations applied immediately.
     */
    fun <T> withMutableSnapshot(block: MutableSnapshot.() -> T): T
}

/**
 * Create a snapshot state list.
 */
fun <T> mutableStateListOf(vararg elements: T): SnapshotStateList<T>

/**
 * Create a snapshot state map.
 */
fun <K, V> mutableStateMapOf(vararg pairs: Pair<K, V>): SnapshotStateMap<K, V>

/**
 * A list that participates in snapshot state management.
 */
interface SnapshotStateList<T> : MutableList<T>, State<List<T>>

/**
 * A map that participates in snapshot state management.
 */
interface SnapshotStateMap<K, V> : MutableMap<K, V>, State<Map<K, V>>

Usage Examples:

// State hoisting pattern
@Composable
fun TodoApp() {
    var todos by remember { mutableStateOf(emptyList<Todo>()) }
    var newTodoText by remember { mutableStateOf("") }
    
    Column {
        TodoInput(
            text = newTodoText,
            onTextChange = { newTodoText = it },
            onAddTodo = { 
                if (newTodoText.isNotBlank()) {
                    todos = todos + Todo(id = generateId(), text = newTodoText)
                    newTodoText = ""
                }
            }
        )
        
        TodoList(
            todos = todos,
            onToggleTodo = { todoId ->
                todos = todos.map { todo ->
                    if (todo.id == todoId) {
                        todo.copy(completed = !todo.completed)
                    } else {
                        todo
                    }
                }
            },
            onDeleteTodo = { todoId ->
                todos = todos.filter { it.id != todoId }
            }
        )
    }
}

@Composable
fun TodoInput(
    text: String,
    onTextChange: (String) -> Unit,
    onAddTodo: () -> Unit
) {
    Row {
        TextField(
            value = text,
            onValueChange = onTextChange,
            label = { Text("New todo") },
            modifier = Modifier.weight(1f)
        )
        Button(onClick = onAddTodo) {
            Text("Add")
        }
    }
}

@Composable
fun TodoList(
    todos: List<Todo>,
    onToggleTodo: (String) -> Unit,
    onDeleteTodo: (String) -> Unit
) {
    LazyColumn {
        items(todos) { todo ->
            TodoItem(
                todo = todo,
                onToggle = { onToggleTodo(todo.id) },
                onDelete = { onDeleteTodo(todo.id) }
            )
        }
    }
}

// Using SnapshotStateList for collection state
@Composable
fun StateListExample() {
    val items = remember { mutableStateListOf<String>() }
    
    Column {
        Button(onClick = { 
            items.add("Item ${items.size + 1}")
        }) {
            Text("Add Item")
        }
        
        LazyColumn {
            itemsIndexed(items) { index, item ->
                Row {
                    Text(item, modifier = Modifier.weight(1f))
                    Button(onClick = { items.removeAt(index) }) {
                        Text("Remove")
                    }
                }
            }
        }
    }
}

data class Todo(val id: String, val text: String, val completed: Boolean = false)
fun generateId(): String = UUID.randomUUID().toString()

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-compose-ui--ui-uikitsimarm64

docs

composables.md

core-ui.md

graphics.md

index.md

input.md

ios-integration.md

layout.md

material-design.md

resources.md

state.md

text.md

window.md

tile.json