Stately is a lightweight Kotlin Multiplatform library that simplifies handling async data
flows like fetching and actions across platforms (Android, JVM, iOS).
Inspired by React hooks like useSWR, useMutation, useQuery, Stately aims to provide:
- Consistent state management for async flows (loading, error, data)
- Built-in revalidation (polling) for fetch
- Action management with loading/error callbacks
- Clean UI integration in Jetpack Compose
This library is not currently published to any public Maven repository.
To use it in your own project:
Run the following command from the root of the project:
./gradlew publishToMavenLocalThis will install the library to your local Maven cache (~/.m2).
In your build.gradle.kts or build.gradle:
repositories {
mavenLocal()
// other repositories like mavenCentral(), google(), etc.
}In your module's dependencies block:
dependencies {
implementation("dev.voir:stately:<version>")
}Replace
<version>with the version from yourbuild.gradle.kts. Currently 1.0.0-alpha01
Make sure to rerun publishToMavenLocal every time you change the library.
Includes:
StatelyFetch<Data, Payload>: declarative data fetching with polling and payload supportStatelyAction<Payload, Response>: single-shot mutation-like executionStatelyFetchResultandStatelyActionResult: unified state containers
A sample Jetpack Compose app with:
- Navigation
- Examples for
StatelyFetch,StatelyAction - Demo with
StatelyFetchContent,StatelyFetchBoundary - Dynamic config panel to toggle revalidation, lazy load, errors
val fetch = StatelyFetch<String, String>(
fetcher = { payload -> api.loadData(payload) },
revalidateInterval = 5000L,
lazy = false,
initialData = null,
initialPayload = "",
).state: exposes loading, error, and data.revalidate(payload?): triggers a new fetch- Revalidates periodically if
revalidateIntervalis set
val action = StatelyAction(
action = { payload -> api.sendSomething(payload) },
onSuccess = { result -> println("✅ Success") },
onError = { error -> println("❌ Failed") }
)
action.execute(payload)Tests are written using pure kotlin.test, kotlinx.coroutines.test
./gradlew stately:checkComposable for rendering based on StatelyFetchResult:
StatelyFetchContent(
state = state,
loading = { Text("Loading") },
error = { e -> Text("Error: ${e.message}") },
content = { data -> Text("Data: $data") }
)A wrapper that handles everything:
StatelyFetchBoundary(
fetcher = { api.getSomething() },
content = { data -> Text(data) }
)- ✅ Android
- ✅ iOS
- ✅ JVM
This library is still under active development. PRs and feedback are welcome.
- File issues
- Suggest features
- Write sample apps for other targets
MIT License – see LICENSE for full details.