Repository navigation
v0.1.0
Async server-state management for Android — caching, deduplication,
stale-while-revalidate, mutations, offline support, and a cache that survives
process death.
A TanStack Query equivalent for Kotlin,
built for how Android actually behaves.
Install
Not on Maven Central yet. JitPack builds it from this tag.
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven("https://jitpack.io")
}
}
// build.gradle.kts
dependencies {
implementation("com.github.dbjpanda.kwery:kwery-core:v0.1.0")
implementation("com.github.dbjpanda.kwery:kwery-android:v0.1.0") // focus + connectivity
implementation("com.github.dbjpanda.kwery:kwery-compose:v0.1.0") // rememberQuery
implementation("com.github.dbjpanda.kwery:kwery-persist:v0.1.0") // cache across process death
testImplementation("com.github.dbjpanda.kwery:kwery-test:v0.1.0") // TestQueryClient
}What is in it
19 of 24 features complete through spec, tests and documentation, behind
367 tests — none of which use a real delay(), so the suite runs in
seconds rather than minutes.
- Queries with
staleTime/gcTime, deduplication, and two orthogonal
status axes sosuccess+fetching(background refresh) andpending+
paused(cold start, offline) are both expressible - Mutations with optimistic updates, typed rollback context, and scopes that
serialise writes which must not race - Offline: queries pause rather than fail, and writes queue durably and
replay after process death - Persistence with hydration that preserves each entry's original age, so a
restored cache is judged fresh or stale correctly - Infinite and paginated queries, with retry applied per page
- Compose bindings and a Flow-first core that works equally well from a
ViewModel
Android-specific choices
These are where Kwery diverges from a direct port, and why it exists:
- Rotation costs nothing. A reattach inside a five-second grace window is a
continuation, not a new mount, so it skips the staleness check. Measured:
without it, rotation at the defaultstaleTime = 0fires a redundant request
every time. - Connectivity means a validated network. A captive portal reports a
perfectly good network on which every request fails; treating "connected" as
"online" means refetching into a black hole. - Focus is process lifecycle, not Activity focus — per-Activity focus fires
on dialogs, permission prompts and the app switcher. - The cache is bounded by count as well as time. A browser tab gets
reloaded; an Android process can live for days.
What is not in it
Stated plainly, because a version number is a promise:
- Not on Maven Central — needs GPG signing and a Portal namespace
- Persistence is file-backed only. Benchmarked: 10 000 entries restore in
3–5 ms, so this is not a startup problem. The cost is write amplification —
every change rewrites the whole file - Three tests need a device: R8 key-encoding survival, captive-portal
detection, and Compose render paths - Devtools, cross-process sync and streamed queries are specified and unbuilt
RELEASE.md is the
full inventory, including nine things deliberately not built and the reason for
each. Documentation is 22
pages, and every identifier in them is checked against the published API on
every build.
Apache-2.0. Feedback and bug reports very welcome — this is early.