Skip to content
Blog

ListenableBuilder Patterns in Flutter: Reactive UI Without Streams

Rebuild parts of your UI from any Listenable with ListenableBuilder — animations, controllers, and notifiers without StreamBuilders.

Published on • November 4, 2026

AI Assistant

ListenableBuilder is the general-purpose rebuild widget: give it any Listenable — a ChangeNotifier, an Animation, a TextEditingController, a scroll controller — and its builder reruns whenever it fires. It replaced the old AnimatedBuilder-only mindset for non-animation use cases.

The basic shape

ListenableBuilder(
  listenable: myNotifier,
  builder: (context, _) {
    return Text('${myNotifier.value}');
  },
)

The second builder argument is the child widget (for optimization); most of the time you ignore it with _.

Rebuilding from a controller

ListenableBuilder(
  listenable: textController,
  builder: (context, _) {
    final length = textController.text.length;
    return Text('$length / 280');
  },
)

This is a cleaner alternative to attaching a listener manually and calling setState — no initState/dispose bookkeeping.

Multiple listenables

ListenableBuilder accepts a listenable that can be a Listenable — but for several sources, compose them:

ListenableBuilder(
  listenable: Listenable.merge([notifierA, notifierB]),
  builder: (context, _) => Text('${notifierA.value} + ${notifierB.value}'),
)

Listenable.merge creates a fan-in that fires when any source fires.

Rebuilding only part of the tree

Place ListenableBuilder as low in the tree as possible. Rebuilding a whole page from a text controller wastes work; wrap just the character counter instead. This is the “islands” mindset applied to state: the narrower the listener scope, the fewer rebuilds.

Takeaway: ListenableBuilder rebuilds from any Listenable — controllers, notifiers, animations — replacing manual listener/setState boilerplate. Scope it low in the tree, and use Listenable.merge to fan in multiple sources.