Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when setting up providers, consuming state, optimizing rebuilds, using ProxyProvider, or migrating from deprecated providers (Provider package).
.claude/skills/evanca-provider/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | -28% | 0% |
| case-02 | ✗→✓ | ▲ Improved | -8% | 0% |
| case-03 | ✗→✓ | ▲ Improved | -17% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 14% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 1% | 0% |
This skill defines how to correctly use the provider package in Flutter applications.
| Provider | Use for | |---|---| | Provider | Exposing any immutable value | | ChangeNotifierProvider | Mutable state with ChangeNotifier | | FutureProvider | Exposing a Future result | | StreamProvider | Exposing a Stream | | ProxyProvider / ChangeNotifierProxyProvider | Objects that depend on other providers |
dartMultiProvider( providers: [ Provider<Something>(create: (_) => Something()), ChangeNotifierProvider(create: (_) => MyNotifier()), FutureProvider<String>(create: (_) => fetchData(), initialData: ''), ], child: MyApp(), )
MultiProvider to group multiple providers and avoid deeply nested trees.ChangeNotifierProvider automatically disposes the model when it is no longer needed.ProxyProvider instead.StackOverflowError.Always specify the generic type for type safety:
dart// Listen and rebuild on change — only valid inside build() or a Provider's update method final count = context.watch<MyModel>().count; // Access without listening — use in callbacks, not inside build() context.read<MyModel>().increment(); // Listen to only part of the state final count = context.select<MyModel, int>((m) => m.count);
Use Consumer<T> or Selector<T, R> widgets when you need fine-grained rebuilds and cannot access a descendant BuildContext:
dartConsumer<MyModel>( builder: (context, model, child) => Text('${model.count}'), child: const ExpensiveWidget(), // rebuilt only once ) Selector<MyModel, int>( selector: (_, model) => model.count, builder: (_, count, __) => Text('$count'), )
Use ProxyProvider or ChangeNotifierProxyProvider for objects that depend on other providers or values that can change:
dartMultiProvider( providers: [ Provider<Auth>(create: (_) => Auth()), ProxyProvider<Auth, Api>( update: (_, auth, __) => Api(auth.token), ), ], )
initState or constructors — use them in build, callbacks, or lifecycle methods where the widget is fully mounted.ChangeNotifier; use Provider.value() with a StatefulWidget if needed.Implement toString or DiagnosticableTreeMixin to improve how your objects appear in Flutter DevTools:
dartclass MyModel with DiagnosticableTreeMixin { final int count; MyModel(this.count); @override String toString() => 'MyModel(count: $count)'; }
ValueListenableProvider is deprecated. Use Provider with ValueListenableBuilder instead:
dartValueListenableBuilder<int>( valueListenable: myValueListenable, builder: (context, value, _) { return Provider<int>.value( value: value, child: MyApp(), ); }, )
Other measured skills in the registry, with their headline benchmark lift.