Skip to main content

RefreshableComputedStateWrapper

A ComputedStateWrapper wrapped in a RefreshIndicator. It takes a RefreshableComputedState and wires pull-to-refresh to its refresh(), while rendering the same loading / failure / ready builders.

class ProfileView extends HookWidget {
const ProfileView({super.key, required this.service});

final ProfileService service;


Widget build(BuildContext context) {
// useAutoComputedState returns a MutableComputedState, which is a RefreshableComputedState.
final profileState = useAutoComputedState(service.load);

return RefreshableComputedStateWrapper<Profile>(
state: profileState,
inProgressBuilder: (context) => const Center(child: CircularProgressIndicator()),
failedBuilder: (context) => const Center(child: Text('Could not load the profile')),
// Swiping down calls state.refresh(); the content must be scrollable for the gesture.
builder: (context, profile) => ListView(children: [Text(profile.name)]),
);
}
}

Constructor

RefreshableComputedStateWrapper<E>({
Key? key,
required RefreshableComputedState<E> state,
required Widget Function(BuildContext) inProgressBuilder,
required Widget Function(BuildContext) failedBuilder,
required Widget Function(BuildContext, E) builder,
bool keepInProgress = false,
});
  • state - a RefreshableComputedState<E>, i.e. one that exposes refresh(). The MutableComputedState returned by useComputedState / useAutoComputedState qualifies.
  • inProgressBuilder / failedBuilder / builder / keepInProgress - identical to ComputedStateWrapper; see that page for the full semantics.

The only addition over ComputedStateWrapper is the surrounding RefreshIndicator: swiping down calls state.refresh(), swallowing a ComputedStateRefreshCancelled so the indicator settles cleanly if the refresh is superseded.

Use cases

  • A single async value that the user should be able to pull to reload - a profile screen, a dashboard card - where you want explicit loading and error builders plus refresh, without wiring the RefreshIndicator yourself.
  • Combine with keepInProgress: true so the current value stays on screen during the pull-to-refresh, rather than collapsing to the loading builder mid-gesture.

For a collection that needs a distinct empty state alongside refresh, use RefreshableComputedIterableWrapper.

Caveats

  • builder must return a scrollable. RefreshIndicator only arms the pull gesture when its child scrolls. A non-scrolling builder result shows the value but can never be pulled - wrap it in a ListView or a SingleChildScrollView with AlwaysScrollableScrollPhysics. The loading and failure builders are already made scroll-fillable by the wrapper.

  • state must be a RefreshableComputedState, not a bare ComputedState. A plain on-demand ComputedState has no refresh() and won't type-check here; use ComputedStateWrapper for those.

  • Everything from ComputedStateWrapper carries over: builder never gets null, failedBuilder gets no error object, and a notInitialized state renders as loading.

See also