π Complete documentation available at flutter-it.dev Check out the comprehensive docs with detailed guides, examples, and best practices!
The easiest state management for Flutter built on get_it
Widgets automatically rebuild when data changes. No ValueListenableBuilder, no StreamBuilder, no FutureBuilderβjust watch your data and your UI stays in sync.
One line instead of 12. No nesting, no boilerplate. Watch multiple values without builder hell.
Part of flutter_it β A construction set of independent packages. watch_it + get_it is the recommended foundation. Add command_it and listen_it when you need them.
- β¨ Zero Boilerplate β No Builders, no
setState, no widget tree nesting - β‘ Automatic Cleanup β Subscriptions disposed automatically when widget destroys
- π― Type Safe β Catch errors at compile time with generics
- π§ Flexible Data Types β Works with Listenable, ValueListenable, Stream, Future
- π Multiple Watches β Watch 3+ values without pyramid of doom
- π§ͺ Test Friendly β Easy to mock and inject dependencies
Learn more about the benefits β
Add to your pubspec.yaml:
dependencies:
watch_it: ^2.2.0
get_it: ^9.0.5 # Recommended - watch_it builds on get_itimport 'package:watch_it/watch_it.dart';
// 1. Create a model with ValueNotifier properties
class CounterModel {
final count = ValueNotifier<int>(0);
void increment() => count.value++;
}
// 2. Register with get_it (using exported 'di' instance)
di.registerSingleton(CounterModel());
// 3. Watch it - widget rebuilds automatically
class CounterWidget extends WatchingWidget {
@override
Widget build(BuildContext context) {
final count = watchValue((CounterModel m) => m.count);
return Column(
children: [
Text('$count'),
ElevatedButton(
onPressed: di<CounterModel>().increment,
child: Text('Increment'),
),
],
);
}
}That's it! No builders, no manual subscriptions. Just watch and rebuild.
Watch multiple values without nesting builders:
class UserDashboard extends WatchingWidget {
@override
Widget build(BuildContext context) {
// Watch multiple values - no nested builders!
final userName = watchValue((UserModel m) => m.name);
final isLoggedIn = watchValue((AuthModel m) => m.isLoggedIn);
final notifications = watchStream(
(NotificationModel m) => m.updates,
initialValue: []
);
if (!isLoggedIn) return LoginScreen();
return Text(
'$userName - ${notifications.data?.length ?? 0} notifications'
);
}
}Replace Builders with simple one-line watch calls:
-
watchValue β Watch
ValueListenableproperties from get_it objects -
watchIt β Watch whole
Listenableobjects registered in get_it -
watchPropertyValue β Watch specific property, rebuilds only when value changes
-
watchStream β Reactive streams without StreamBuilder
-
watchFuture β Reactive futures without FutureBuilder
-
watch β Watch any local Listenable
Execute side effects without rebuilding:
-
registerHandler β React to ValueListenable changes (show dialogs, navigate)
-
registerStreamHandler β React to stream events
-
registerFutureHandler β React to future completion
-
registerChangeNotifierHandler β React to ChangeNotifier changes
Powerful functions for StatelessWidgets:
-
createOnce β Create objects on first build, auto-dispose on widget destroy
-
callOnce β Execute function only on first build
-
callOnceAfterThisBuild β Execute function once after current build completes
-
callAfterEveryBuild β Execute function after every rebuild
-
pushScope β Automatic get_it scope management tied to widget lifecycle
All watch* calls must:
- Be called inside
build()method - Be called in same order every build
- Not be conditional (no
ifwrapping watch calls)
Why these rules? watch_it uses index-based retrieval similar to React Hooks. Changing the order breaks the mapping between calls and stored data.
Read the detailed explanation β
Choose the widget type that fits your needs:
- WatchingWidget β Extends
StatelessWidget, use for simple widgets - WatchingStatefulWidget β Extends
StatefulWidget, use when you need lifecycle or local state - WatchItMixin β Add to existing
StatelessWidgetwithwith WatchItMixin - WatchItStatefulWidgetMixin β Add to existing
StatefulWidgetwithwith WatchItStatefulWidgetMixin
Built on get_it β watch_it is designed to work with get_it's service locator pattern. Register your models, services, and business logic with get_it, then watch them reactively.
// Register with get_it
di.registerLazySingleton(() => UserManager());
di.registerLazySingleton(() => TodoManager());
// Watch them in any widget
class MyWidget extends WatchingWidget {
@override
Widget build(BuildContext context) {
final user = watchIt<UserManager>();
final todos = watchValue((TodoManager m) => m.todos);
return ListView(...);
}
}Want more? Combine with other flutter_it packages:
-
get_it β Recommended pairing. Service locator for dependency injection. Access global services with
di<T>(). -
Optional: command_it β Command pattern with loading/error states. Watch Commands reactively for automatic UI updates.
-
Optional: listen_it β ValueListenable operators (map, debounce, where). Watch reactive collections (ListNotifier, MapNotifier, SetNotifier).
π‘ flutter_it is a construction set β watch_it + get_it is the recommended foundation. Add command_it and listen_it when you need advanced features. Each package works independently.
- Getting Started Guide β Installation, basic concepts, first steps
- Your First Watch Functions β Learn
watchValue()with examples - More Watch Functions β
watchIt(),watchPropertyValue(),watch() - Watching Streams & Futures β Replace builders with one-line watches
- Handler Functions β Side effects without rebuilding
- Lifecycle Helpers β
createOnce(),callOnce(), disposal - Watch Ordering Rules β Critical reading! Understanding the order requirement
- Debugging & Troubleshooting β Common errors, tracing, solutions
- Best Practices β Patterns, performance, testing
- Advanced Integration β Scopes, async initialization, named instances
- Discord β Get help, share ideas, connect with other developers
- GitHub Issues β Report bugs, request features
- GitHub Discussions β Ask questions, share patterns
Contributions are welcome! Please read the contributing guidelines before submitting PRs.
MIT License - see LICENSE file for details.
Part of the flutter_it ecosystem β Build reactive Flutter apps the easy way. No codegen, no boilerplate, just code.
