This is a clean, simple example of how to use the Provider API in your flutter app to do state management. The basic functionality is akin to redux, if you are from a React background.
The key aspects of using this are as follows:
- KeepYour provider is a Dart class which has all the shared state as required by your application. For example, if you are implementing a shopping application, this class may hols a list of inventory items as well as the the cart data (items ordered, total value, etc.).
- This class should also implement all the business logic, as required by the application. For instance, it should add up all the total cost of items on order.
- This class should extend ChangeNotifier (in package flutter/material.dart). This ChangeNotifier is responsible for "broadcasting" a notification to all widgets who are listening to changes in the state.
- Our provider class must call "notifyListeners" each time the state changes. For example, if an item is added to the shopping cart, we should re-calculate the totals and call notifyListeners in the ChangeNotifier class.
Here is the complete class:
class CounterProvider extends ChangeNotifier { int mCounter = 0; int getCurrentCount() => mCounter; void incrementCounter(){ ++mCounter;
// Since the state has changed, we must notify
notifyListeners();
}
void resetCount(){
mCounter = 0;
notifyListeners();
}
}
Next, we need to add a ChangeNotificationProvider class into our widget hierarchy. This provider will be then be accessible to children in the hierarchy. The ChangeNotificationProvider takes two parameters; a function create which creates the provider and a child . Here is how to inject the CNP into the hierarchy tree.
class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); // This widget is the root of your application. @override Widget build(BuildContext context) { // NB: We wrap the UI hirearchy in a ChangeNotificationProvider class return ChangeNotifierProvider( create: (context) => CounterProvider(), child: MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ), ); } }
Finally, we need to access the state in the UI and also, the widget must be updated whenever the state changes (e.g an item is added to the cart). But how does the UI component listen to the state change events?
Any widget that is a child (no matter how deep) of the ChangeNotificationProvider can get a handle to the state with a call to a Provider class. This Provider class is responsible of looking up the hierarchy and fetching the state of the specific class:
CounterProvider p; @override Widget build(BuildContext context) { p = Provider.of<counterprovider>(context, listen:true );
Notice how we have passed the context and
Here is the complete code.
import 'package:flutter/material.dart'; import 'package:my_app/counter_provider.dart'; import 'package:provider/provider.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); // This widget is the root of your application. @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) => CounterProvider(), child: MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ), ); } } // ------------------------------------------------------------ class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { late CounterProvider p; void _increment(){ p.incrementCounter(); } @override Widget build(BuildContext context) { p = Provider.of<CounterProvider>(context, listen:true ); int aCount = p.getCurrentCount(); return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'You have pushed the button this many times:', ), Text( '$aCount', style: Theme.of(context).textTheme.headline4, ), ElevatedButton(onPressed: () => p.resetCount(), child: const Text("Reset counter"),) ], ), ), floatingActionButton: FloatingActionButton( onPressed: _increment, tooltip: 'Increment', child: const Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); } }
And the provider class
import 'package:flutter/material.dart'; class CounterProvider extends ChangeNotifier { int mCounter = 0; int getCurrentCount() => mCounter; void incrementCounter(){ ++mCounter; notifyListeners(); } void resetCount(){ mCounter = 0; notifyListeners(); } }
No comments:
Post a Comment