steady_async 0.1.0
steady_async: ^0.1.0 copied to clipboard
Perception-aware async UX for Flutter with calm loading, actions, retries, and pagination.
steady_async #
Calm, production-ready async UX for Flutter. steady_async prevents flashing
spinners, keeps existing content visible during refresh, ignores stale results,
and provides consistent retry, action, and pagination states.
Why use it? #
A normal FutureBuilder exposes snapshots; your app still has to solve loader
timing, refresh continuity, retry safety, stale completions, empty states,
accessibility, and motion. steady_async makes those behaviors one reusable
policy while remaining independent of Provider, Riverpod, BLoC, and GetX.
Install #
dependencies:
steady_async: ^0.1.0
Flutter 3.22+ and Dart 3.4+ are supported.
Future #
Pass a factory, not an already-created Future, so retry is safe:
SteadyAsyncBuilder<List<User>>(
load: api.fetchUsers,
isEmpty: (users) => users.isEmpty,
dataBuilder: (context, users) => ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) => Text(users[index].name),
),
)
Fast operations do not flash a loader. Refreshes preserve previous content by
default. Use SteadyAsyncController when you need explicit refresh or reload:
final controller = SteadyAsyncController(api.fetchUsers);
await controller.load();
await controller.refresh();
await controller.retry();
Async actions #
SteadyButton<void>(
action: form.save,
child: const Text('Save'),
successChild: const Text('Saved'),
)
Duplicate taps are dropped by default. Choose latestWins or sequential for
searches and queues.
Pagination #
final pages = SteadyPagedController<Post, String>(
firstPageKey: 'first',
loadPage: api.fetchPosts,
);
SteadyPagedListView<Post, String>(
controller: pages,
itemBuilder: (context, post, index) => PostTile(post),
)
The controller supports cursor or offset keys, guards overlapping requests, retains items after append failures, and retries the failed page.
Customize globally #
SteadyTheme(
data: const SteadyThemeData(
policy: SteadyTransitionPolicy(loaderDelay: Duration(milliseconds: 150)),
),
child: const MyApp(),
)
All loading, empty, error, retry, transition, timing, and empty-predicate APIs can be replaced. Built-in messages support English, Hindi, Arabic, Spanish, French, German, Brazilian Portuguese, Simplified Chinese, and Japanese.
See the interactive showcase and the repository.