flutter_network_guard 0.3.0
flutter_network_guard: ^0.3.0 copied to clipboard
Network reliability toolkit for Flutter: real internet checks, server health, retry with backoff, offline queue, caching and network-aware widgets.
Changelog #
0.3.0 #
Mostly bug fixes, plus a few small additions. The public API is unchanged (only additions), but a few behaviours are now corrected — see "Behaviour changes".
Fixed #
- Server health checks no longer re-trigger themselves. With
serverHealthChecksconfigured, every health result started another full check, so servers and the reachability endpoints were hit in a loop (and multiplied with more than one server). Server health is now refreshed once per regular check. - Overlapping checks are merged. A connectivity event, the periodic
timer and a manual
checkInternet()arriving together no longer run parallel checks that could finish out of order; one follow-up pass is scheduled instead. - No more crash when disposing mid-check. An in-flight check that
finished after
NetworkGuard.reset()/ re-initialize()could add to a closed stream. Timer-driven checks now also log failures instead of leaking unhandled async errors. networkStreamand callbacks only fire on real changes. Latency changes on almost every poll, which made the stream,onNetworkChangedand the event history fire every check. Latency/timestamp updates still refreshNetworkGuard.info, but don't notify.- Offline snapshot is clean. Going fully offline no longer keeps the
old latency, quality or
serverReachablevalue. - Deduplicator: a failed call with a
keyno longer produces an unhandled async error, andreplacePreviousno longer lets the old call's completion untrack the new one. execute():CachePolicy.networkOnlynow returnsNetworkOfflinewhile offline instead of attempting the request;fromCacheis now correct forstaleWhileRevalidateand for anetworkFirstfallback.- Retry: a custom
retryIfcan no longer cause a cancelled request to be retried. - Offline queue: no duplicated tasks when the queue was first touched
concurrently; tasks left
processingby an app kill are retried instead of stuck forever;maxQueueSizenow counts only waiting tasks, so completed ones no longer fill the queue up; the queue is saved after each task, so a crash can't re-send already delivered ones; retry delay is measured from the failure time. - Persisted queue: unreadable or corrupt entries are skipped instead of breaking the whole queue.
- Server health:
lastSuccessAtis tracked per server; response bodies are released;NetworkGuard.checkServercloses its HTTP client. OfflineBannerno longer flashes "Back online" for a frame.
Added #
dioRetryPredicate()(Dio adapter): retries timeouts, connection errors andRetryPolicy.retryableStatusCodesonly.retryableStatusCodeswas previously not used anywhere.RetryPolicy.defaultRetryableStatusCodes.OfflineQueue.clearCompleted().
Changed #
- Minimum SDK lowered to Dart
^3.8.0/ Flutter>=3.32.0(was Dart^3.13.0), so the package installs on much older toolchains. - README rewritten to be shorter; installation snippet now shows the current version.
Behaviour changes #
onServerRestoredcan now also fire after a period with no connection at all, since the server is then reported unreachable.- A function passed as the queue
executorthat throws is retried like one that returnsfalse(this was always the case; the docs said otherwise).
0.2.0 #
New, fully backwards-compatible features — nothing here changes the behavior of existing code that doesn't opt into the new APIs.
- Reactive offline queue status:
OfflineQueue.changesis a new broadcastStream<QueueStats>that emits whenever the queue's contents change (add, remove, a task moving between pending / processing / completed / failed / expired).OfflineQueue.statsis a synchronous snapshot for reading it on demand. Lets you show a "3 items waiting to sync" badge reactively instead of pollingqueue.pending.lengthon a timer. - Optional per-task retry backoff in the offline queue:
OfflineQueuetakes a new optionalretryDelaycallback (Duration Function(int retryCount)). When set, a task that fails but has retries left waits for that computed delay before it's eligible for anotherprocessPending()attempt, instead of being retried on the very next call as before. Leaving it unset keeps the original immediate- retry behavior. Backed by a newQueuedRequest.nextRetryAtfield, serialized alongside the rest of the task so it survives a persisted queue's own upgrade — queues written by older versions deserialize it asnull(immediately eligible), same as before this existed. OfflineQueue.dispose(): closes the newchangesstream. Optional for the common case of one queue living for the app's lifetime; useful if you create queues dynamically (e.g. in tests).RetryPolicy.onRetry: an optional(attempt, error, delay) {}callback invoked byRetryEngineright before it sleeps for a retry. Useful for a "Retrying (2/3)..." toast or analytics without wrapping or subclassing anything.NetworkGuard.queueOrNull/NetworkGuard.cacheOrNull: the same asNetworkGuard.queue/NetworkGuard.cache, but returnnullinstead of throwingStateErrorwhen noOfflineQueue/CacheManagerwas configured — handy for optional UI that shouldn't need a try/catch just to check.NetworkGuardListenable: aChangeNotifierwrapper aroundNetworkGuard.networkStream/.info, forChangeNotifierProvider,AnimatedBuilder/ListenableBuilder, or any other API in your state management setup that expects aListenablerather than a rawStream. Purely additive — the stream-based API is unchanged and still the recommended default for anything that isn't already listenable-shaped.NetworkDebugPanelnow shows a queue line (pending/processing/failed counts) automatically whenNetworkGuardConfig.offlineQueueis set, driven by the newOfflineQueue.changesstream.- Fixed:
OfflineQueue.clear()no longer skips loading a persisted queue before clearing it, so callingclear()before anything else has touched the queue now correctly wipes persisted storage too instead of only the in-memory list.
0.1.2 #
- Added screenshots and demo GIF to pub.flutter-io.cn listing.
- Fixed README image links (raw GitHub URLs).
0.1.1 #
Bugfixes found while compiling on a real Flutter/Windows setup:
- Fixed
RetryExhaustedException'smessageparameter, which didn't compile because it tried to forward to a positional super parameter as a named one. - Fixed
NetworkGuard.initialize()awaitingNetworkService.dispose(), which returnsvoid, not aFuture. - Fixed a non-exhaustive switch in the connectivity adapter caused by newer
connectivity_plusversions addingConnectivityResult.satellite; it now falls back toConnectivityType.otherfor any future values too. - Fixed
NetworkQualityThresholds's ordering check, which usedDuration's<operator inside aconstconstructor assert — not allowed in Dart's constant evaluation. The check now runs atclassify()call time instead.
0.1.0 #
Initial release.
- Connectivity detection (
ConnectivityService, wrappingconnectivity_plus). - Real Internet reachability with multi-endpoint fallback (
InternetChecker). - Server health checks and periodic monitoring, independent of Internet
reachability (
ServerHealthChecker,ServerHealthMonitor). - Latency-based network quality estimation (
NetworkQuality). - Unified
NetworkGuardfacade:initialize,instance,networkStream,checkInternet,checkServer, recovery callbacks, app-lifecycle awareness, debounced checks, and event history. - Retry engine with fixed/linear/exponential backoff, jitter, and smart
default retry rules (
RetryPolicy,RetryEngine). NetworkGuard.executefor protected calls: retry, deduplication, cancellation, timeout, and a typedNetworkResult(success / failure / offline / timeout / cancelled / queued).- Request deduplication (
RequestDeduplicator), cooperative cancellation (CancelToken), and stale-response protection (RequestManager). - Offline queue with priorities and optional persistence
(
OfflineQueue,QueuedRequest,SharedPreferencesQueueStorage). - Opt-in cache with TTL and five cache policies, including
stale-while-revalidate (
CacheManager,CachePolicy). - Network-aware widgets:
NetworkAware,NetworkStatusBanner,OfflineBanner,NetworkGuardBuilder,NetworkGuardButton,NetworkDebugPanel. - Logging (
NetworkLogger, off by default) and metrics (NetworkMetrics). - Optional Dio interceptor and
package:httpclient adapter — neither HTTP client is required to use the core package. - Example app demonstrating every module.
Known limitations #
- The Dio adapter adds
dioas a package dependency even for apps that don't use it; a future release may split it into a companion package (see Roadmap in the README) to make it a true zero-cost opt-in. - Network quality is a latency-based estimate only, not a bandwidth measurement.
- Successful offline queueing does not guarantee eventual server delivery.
