flutter_query_client 1.2.0
flutter_query_client: ^1.2.0 copied to clipboard
A TanStack Query-inspired server state management library for Flutter. Handles caching, background refetching, pagination, mutations, and network-aware fetching out of the box.
1.2.0 #
Breaking changes #
- None — all changes are backwards-compatible. Existing subclasses that already override
initialPageParamandlimitcontinue to work unchanged.
New Features #
MultiQueryProvider— provide multiple query and infinite-query controllers without deep widget nesting; each entry is a builder functionWidget Function(Widget child), applied top-to-bottomQueryConsumer<C, T>— combinesQueryBuilder+QueryListenerin a single widget, eliminating the need to nest them; works withQueryControllerandMutationControllerInfiniteQueryConsumer<C, T>— same asQueryConsumerfor infinite queries; theList<T>wrapper is baked into the type so only the item type is requiredQuerySelector<C, T, S>— aBlocSelectorscoped toQueryState<T>; rebuilds only when the selected derived valueSchanges, ideal for counters, flags, and other narrow slices of stateInfiniteQuerySelector<C, T, S>— same asQuerySelectorfor infinite queries;List<T>is baked inInfiniteQueryListener<C, T>— mirrorsInfiniteQueryBuilderfor the listener side; eliminates the verboseQueryListener<C, List<T>>type annotationQueryObserver— aBlocObserversubclass that filters events to query and mutation controllers and re-exposes them as typed, cache-key–aware hooks (onQueryCreate,onQueryChange,onQueryError,onQueryClose);onQueryChangereceives bothcurrentStateandnextStatematching standardBlocObserver.onChangesemanticsQueryDefaults.initialPageParam— global default first-page parameter for everyInfiniteQueryController; defaults to0so zero-indexed integer pagination requires no per-controller override. Set to1for one-indexed APIs or any custom value for cursor-based APIsQueryDefaults.limit— global default page size for everyInfiniteQueryController; defaults to20. Set once inQueryClientProviderinstead of repeating@override int get limit => Nin every subclassInfiniteQueryController.initialPageParam— no longer abstract; falls back toQueryDefaults.initialPageParamcast toPageParam. Override in a subclass only when that controller's starting param differs from the global defaultInfiniteQueryController.limit— now falls back toQueryDefaults.limitinstead of a hardcoded20. Override per-controller when neededQueryClientProvider(observer:)— register aQueryObserverdirectly inQueryClientProvideralongside defaults and logging, keeping all global setup in one place; the constructor callsQueryClient.setObserverinternallyQueryClient.setObserver(BlocObserver)— lower-level escape hatch for registering an observer outside the widget tree;QueryClientProvider(observer:)is preferred at startup- Mutation widgets —
MutationController<T>already emitsQueryState<T>, soQueryBuilder,QueryListener,QueryConsumer, andQuerySelectorall work with mutations out of the box; no separateMutationBuilderorMutationListenerneeded
Example #
- Added a Widgets tab to the example app showcasing every widget in the package with live interactive demos:
MultiQueryProvider,QueryConsumer,QuerySelector,InfiniteQueryListener,InfiniteQuerySelector,InfiniteQueryConsumer,MultiQueryListener, andQueryObserver(including mutations viaQueryBuilder/QueryListener/QueryConsumer/QuerySelector) - Registered
_AppQueryObserverinmain()demonstrating the observer pattern end-to-end
1.1.0 #
Fixes #
- Fixed race condition in
InfiniteQueryController._executeFirstPagecache-hit branch — missing_filterVersioncheck afterawait Future.delayed(Duration.zero)could cause stale filter data to be emitted ifsetParamswas called concurrently - Fixed race condition in
InfiniteQueryController._executeFirstPagepause branch — same missing version check allowed apausedstate emit to overwrite state set by a concurrentsetParamscall - Fixed
InfiniteQueryController.loadMorenot calling_startRefetchInterval()on success — polling would never start ifloadMorewas the first successful fetch operation
1.0.1 #
Fixes #
- Removed unnecessary
package:meta/meta.dartimport fromQueryControllerandInfiniteQueryController— elements are already available viapackage:flutter/foundation.dart - Removed
@internalannotation fromhandleRemount()in both controllers - Fixed unresolved dartdoc references in
QueryLoggerandRefetchOnMount— replaced[Logger.root.onRecord]and[staleTime]with backtick code spans
1.0.0 #
Initial stable release.
Features #
- QueryController — fetch and cache server data with automatic stale-while-revalidate, retry with exponential backoff, refetch on mount, and refetch on reconnect
- MutationController — user-triggered mutations with lifecycle hooks (
onSuccess,onMutationError,onSettled) and optimistic cache update support - InfiniteQueryController — paginated / infinite-scroll queries with
loadMore(),hasMore, cursor or page-number pagination, and item-level cache helpers (updateItem,removeItem,appendItem,prependItem) - QueryClient — singleton two-level cache (
baseKey+ serialized params) with stale-time tracking, garbage collection, and active observer registry - QueryClientProvider —
InheritedWidgetfor injectingQueryClientand globalQueryDefaultsinto the widget tree - QueryProvider / InfiniteQueryProvider —
StatefulWidgetwrappers with remount detection viaTickerModeforIndexedStackandVisibilitysupport - QueryBuilder / InfiniteQueryBuilder — reactive builders that rebuild on state changes
- QueryListener / MultiQueryListener — side-effect widgets that respond to success and error without rebuilding the tree
- QueryState — Freezed-based immutable state with
status,fetchStatus,isStale, and convenience getters - NetworkConnectivityObserver — true L7 connectivity verification (HTTP HEAD), debounced events (500ms), lazy initialization
- QueryDefaults — global configuration for stale time, gc time, retry count, retry delay, refetch interval, network mode, error transform, and logging
- QueryLogger — opt-in structured logging with customizable handlers