| Observe | store.observe() / store.observe(key) → Flow<StoreResult<T>> |
| Read latest result synchronously | store.get() / store.get(key) → StoreResult<T> |
| Read latest value/error synchronously | store.getOrNull() / store.failureOrNull() (key variants for keyed) |
| Local-only store (no remote fetcher) | builder.disableFetcher().build(onObserve = { ... }) (simple & keyed) |
| Pagination: total item count | PagedList(items, nextKey, totalCount = n); read result.totalPagedItemsCount (-1 if unknown; shortcut for result.metadata.totalPagedItemsCount) |
| Await first completed result | store.observe().firstGetOrThrow() (suspend; value or throws) |
| Reload from the UI (try-again / pull-to-refresh) — PREFERRED | result.invalidate() on the rendered StoreResult; reloads the origin store with no ViewModel/repository plumbing |
| Pull-to-refresh (keep content visible) | Observe with LoadRequest.Silent, then result.invalidate(); progress shows via result.isBackgroundLoading() |
Try-again (reload showing Loading) | result.invalidate() on the failed result (default request re-shows Loading) |
| Keep content per reload trigger (invalidate vs query change) | LoadRequest.builder().keepContentOnLoad() (invalidate) and/or .keepContentOnQuery() (query change), then .build(); each unset trigger shows Loading. LoadRequest.Silent = both (see api.md) |
| Reload without a result at hand (old way, still valid) | store.invalidateAsync() / store.invalidate() (key variants for keyed) |
| Replace cached result outright | store.updateWith(StoreResult.Loaded(new)) / store.updateWith(key, ...) |
| Read-modify-write loaded value | store.updateIfSuccess { old -> new } / store.updateIfSuccess(key) { old -> new } (no-op unless Loaded) |
| Optimistic update (auto-revert on failure) | store.optimisticUpdate { old -> emit(new); realUpdate() } |
| Query: store owns it (imperative) | builder.withQuery(initialQuery) → store.submitQueryAsync(query) / store.queryFlow |
| Query: caller owns it (external state flow) | builder.withQuery { stateFlow } → plain store follows the flow (no submitQuery) |
| Query: caller owns it (external any flow) | builder.withQuery(initialQuery) { anyFlow } → plain store follows the flow (no submitQuery) |
| Keys currently active (observed / in cache window) | keyedStore.activeKeys → StateFlow<Set<Key>> |
| Pagination: report visible item | store.onItemRendered(index) |
| Pagination: next-page status | result.nextPageState (Idle/Pending/Error(retry)) |
| React while store is observed (connect to other stores/events) | .whenActive { ... } chained after build; this is the store, block runs while observed & is cancelled on cache release (see patterns.md "Relations between stores") |
| Attach/read custom result flags (metadata) | PagedList(items, nextKey, metadata = MyMeta(...)) / emit(v, metadata = MyMeta(...)); read result.metadata.get<MyMeta>() (see api.md) |
| Tag a reload/query with metadata (why it happened) | invalidate/invalidateAsync/invalidateAllAsync/submitQuery(Async) all take an optional metadata: ContainerMetadata, merged into the emitted result; mark it ContainerMetadata.OneShot to drop it on the next load (see api.md) |
Strip metadata for tests / equality (assertEquals) | result.raw() → same Loading/Loaded/Failed with all metadata dropped, so results compare by value/exception only |