decompose-router 0.9.0 Help

Overview

Alt text

Kotlin Experimental Build Kotlin Maven Central

badge-android badge-wearos badge-desktop badge-ios badge-browser

A Compose-multiplatform navigation library that leverage Decompose to create an API inspired by Conductor

Features

  • 🚏 A Router that manages a stack, pages or slot for your screen configurations

  • 📦 rememberOnRoute() lets you retain your state holders across configuration changes and gets cleared when the user leaves the screen

  • 🚉 Multiplatform! Supports Android, WearOS, Desktop, iOS and Web

At a glance

// Declare your screen configurations for type-safety @Serializable sealed class Screen : Parcelable { data object List : Screen() data class Details(val detail: String) : Screen() } @Composable fun ListDetailScreen() { // Create a router with a stack of screen configurations 🚏 val router: Router<Screen> = rememberRouter { listOf(List) } // Hoist your screens for each configuration 🏗️ RoutedContent(router = router) { screen -> when (screen) { List -> ListScreen( // Navigate by pushing new configurations on the router 🧭 onSelectItem = { detail -> router.push(detail) } ) is Details -> DetailsScreen(screen.detail) } } } @Composable fun DetailsScreen(detail: String) { // 📦 Scope an instance (a view model, a state-holder or whatever) to a route with [rememberOnRoute] // This makes your instances survive configuration changes (on android) 🔁 // And holds-on the instance as long as it is in the backstack 🔗 // Pass in key if you want to reissue a new instance when key changes 🔑 (optional) val viewModel: DetailViewModel = rememberOnRoute(key = detail) { // this: RouterContext DetailViewModel(this, detail) // Optional, if you want your coroutine scope to be cancelled when the screen is removed from the backstack .apply { doOnDestroy { cancel() } } } val state: DetailState by viewModel.states.collectAsState() Text(text = state.detail) } class DetailViewModel(context: RouterContext, detail: String): CoroutineScope { // Optional, if you want to scope your coroutines to the lifecycle of this screen override val coroutineContext: CoroutineContext = Dispatchers.Main + SupervisorJob() // If you want your state to survive process death ☠️ derive your initial state from [RouterContext.state] private val initialState: DetailState = context.state(DetailState(detail)) { states.value } private val stateFlow = MutableStateFlow(initialState) val states: StateFlow<DetailState> = stateFlow }
Last modified: 04 December 2024