┌───────────────────────────┐ │ Counter App │ ├───────────────────────────┤ │ │ │ 0 │ │ │ │ [+] [-] │ │ │ └───────────────────────────┘
Provider package in Flutter - Mini App: Build & Ship
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Counter with Provider', home: // TODO: Wrap HomeScreen with Provider ); } } class Counter with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } void decrement() { _count--; notifyListeners(); } } class HomeScreen extends StatelessWidget { const HomeScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Counter with Provider')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // TODO: Display counter value // TODO: Add buttons to increment and decrement ], ), ), ); } }
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (_) => Counter(), child: MaterialApp( title: 'Counter with Provider', home: const HomeScreen(), ), ); } } class Counter with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } void decrement() { _count--; notifyListeners(); } } class HomeScreen extends StatelessWidget { const HomeScreen({super.key}); @override Widget build(BuildContext context) { final counter = context.watch<Counter>(); return Scaffold( appBar: AppBar(title: const Text('Counter with Provider')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '${counter.count}', style: const TextStyle(fontSize: 48), ), const SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: counter.increment, child: const Text('+'), ), const SizedBox(width: 20), ElevatedButton( onPressed: counter.decrement, child: const Text('-'), ), ], ), ], ), ), ); } }
We wrapped the entire app with ChangeNotifierProvider to provide the Counter instance to all widgets below. The Counter class extends ChangeNotifier and holds the counter state with methods to increment and decrement it, calling notifyListeners() to update the UI.
In HomeScreen, we use context.watch<Counter>() to listen for changes and rebuild the widget when the counter updates. The counter value is shown in a large text widget. Two buttons call the increment and decrement methods to update the counter reactively.
This setup cleanly separates state management from UI and uses Provider to share state easily.
┌───────────────────────────┐ │ Counter App │ ├───────────────────────────┤ │ │ │ 0 │ │ │ │ [+] [-] │ │ │ └───────────────────────────┘
Practice
What is the main purpose of the Provider package in Flutter?
Solution
Step 1: Understand Provider's role
Provider is designed to help share and manage data across different parts of a Flutter app.Step 2: Compare with other options
Animations, user input, and styling are handled by other Flutter features, not Provider.Final Answer:
To share and manage app data easily across widgets -> Option CQuick Check:
Provider = Data sharing and management [OK]
- Confusing Provider with animation tools
- Thinking Provider handles user input
- Assuming Provider styles widgets
Which of the following is the correct way to provide a ChangeNotifier model using Provider?
?Solution
Step 1: Identify correct Provider constructor
For ChangeNotifier models,ChangeNotifierProvider.createis the recommended way to create the model instance.Step 2: Check other options
Provider(create: (_) => MyModel(), child: MyApp()) uses generic Provider which doesn't listen to ChangeNotifier. ChangeNotifierProvider(value: MyModel(), child: MyApp()) usesvaluewhich is discouraged for new instances. ChangeNotifierProvider(builder: (_) => MyModel(), child: MyApp()) uses a non-existentbuilderparameter.Final Answer:
ChangeNotifierProvider(create: (_) => MyModel(), child: MyApp()) -> Option DQuick Check:
Use create with ChangeNotifierProvider [OK]
- Using Provider instead of ChangeNotifierProvider
- Using value instead of create for new objects
- Using builder instead of create
Given this code snippet, what will be printed when the button is pressed?
class Counter extends ChangeNotifier {
int value = 0;
void increment() {
value++;
notifyListeners();
}
}
// Inside a widget:
final counter = Provider.of<Counter>(context);
print(counter.value);
counter.increment();
print(counter.value);Solution
Step 1: Check initial value
The counter starts at 0, so the first print outputs 0.Step 2: After increment
The increment method increases value to 1 and calls notifyListeners, so the second print outputs 1.Final Answer:
0 then 1 -> Option AQuick Check:
Initial 0, incremented to 1 [OK]
- Assuming value changes before first print
- Ignoring notifyListeners effect
- Confusing initial and updated values
What is wrong with this Provider usage code?
ChangeNotifierProvider(
create: (context) => MyModel(),
child: Consumer<MyModel>(
builder: (context, model, child) {
return Text(model.data);
},
),
);Solution
Step 1: Verify the code structure
The code correctly uses ChangeNotifierProvider with create to instantiate MyModel and passes it to a Consumer child that rebuilds on model changes.Step 2: Review other options
MaterialApp is not required as an ancestor of Provider (Provider often wraps MaterialApp). Consumer can be a direct child. The create parameter is correct; value is not needed.Final Answer:
No error, code is correct -> Option BQuick Check:
Valid Provider + Consumer setup [OK]
- Thinking MaterialApp must be an ancestor
- Believing Consumer cannot be a direct child
- Confusing create with required value parameter
You want to update UI only when a specific field count changes in your ChangeNotifier model. Which approach with Provider is best?
Solution
Step 1: Understand selective listening
Selector allows widgets to listen to only part of the model, rebuilding only when that part changes.Step 2: Compare other options
Consumer rebuilds on any change, not selective. Provider.of with listen:false doesn't rebuild. ChangeNotifierProvider.value is unrelated to selective rebuild.Final Answer:
Use Selector to listen only to count changes -> Option AQuick Check:
Selector = selective rebuild [OK]
- Using Consumer causing unnecessary rebuilds
- Using listen:false which disables rebuild
- Confusing Provider.value with selective listening
Ready to prove it?
Pass the test and this pattern moves unknown
