How to Use Provider for State Management in Flutter || Part - 1

Provider is one of the recommended state management options when using Flutter. It simplifies data flow within your app, making it more manageable and scalable. Here’s a brief overview:
What is Provider?
Provider is a package in Flutter that allows you to manage application state efficiently.
It follows the provider design pattern, enabling components to consume data without needing to know the source of that data.
This decoupling makes it easier to refactor, test, and maintain your code.
How does it work?
When you place a
Providerwidget in your widget tree, all its children have access to the values exposed by it.There are different types of providers, but for this explanation, let’s focus on
ChangeNotifierProvider.ChangeNotifierProviderallows you to listen to changes in the provider and automatically rebuilds widgets when needed.You can create your own custom providers by extending
ChangeNotifieryou can create your own custom providers by extendingChangeNotifieror other provider classes.
Example: Creating a ThemeProvider
Suppose you want to change the main colour of your app dynamically.
You can create a
ThemeProviderclass that extendsChangeNotifier.It exposes a
mainColorvalue and achangeThemeColorfunction to update it.When the
mainColorchanges, the class notifies its listeners usingnotifyListeners().
Usage: Wrapping the Widget Tree
In your app, wrap the root widget (usually
MaterialApp) with aChangeNotifierProvider<ThemeProvider>.Use a
Consumer<ThemeProvider>widget to access the value ofThemeProviderwithin your widgets.For example:
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider<ThemeProvider>( create: (context) => ThemeProvider(), child: Consumer<ThemeProvider>( builder: (context, themeProvider, child) => MaterialApp( // Your app content here ), ), ); } }Now any child widget can access and update the main color using
ThemeProvider.mainColor.
How to Use provider in a Flutter Project
Provider is a powerful state management solution for Flutter. Let’s walk through the steps to use it in your project:
Add the Provider Package:
Open your
pubspec.yamlfile and add theproviderdependency:dependencies: flutter: sdk: flutter provider: ^6.1.2Run
flutter pub getto fetch the package.
Create a Provider Class:
Create a new Dart file (e.g.,
data.dart) to store your data.Define a class (e.g.,
Counter) that extendsChangeNotifier.Inside this class, declare your state variables (e.g.,
_count).
Expose State with the Provider:
In your
Counterclass, provide methods to modify the state (e.g., incrementing the count).Use
notifyListeners()to notify listeners when the state changes.
Wrap Your App with the Provider:
In your
main.dart, wrap your app with aChangeNotifierProvider:void main() { runApp( ChangeNotifierProvider( create: (context) => Counter(), child: MyApp(), ), ); }
Access State in Widgets:
Use
Consumer<Counter>to access the state within your widgets:Consumer<Counter>( builder: (context, counter, child) { return Text('Count: ${counter.count}'); }, )
ChangeNotifierProvider in Flutter:
ChangeNotifierProvider is a class from the provider package in Flutter that links the lifecycle of a ChangeNotifier to widgets in the widget tree. Let’s break it down:
What is a
ChangeNotifier?A
ChangeNotifieris a simple class in the Flutter SDK that provides change notification to its listeners.When something is a
ChangeNotifier, you can subscribe to its changes. It acts as an observable, notifying listeners when its internal state changes.
How does
ChangeNotifierProviderwork?ChangeNotifierProvideris responsible for creating and supplying an instance of aChangeNotifierdirectly to the UI.It ensures that when the
ChangeNotifieremits a signal(due to changes).,dependent widgets are notified and can rebuild accordingly.
Difference between
ChangeNotifierProviderandProvider:The
Providerclass exposes a value to all widgets but doesn’t listen to changes from that value.In contrast,
ChangeNotifierProviderlistens to changes from theChangeNotifierand provides the updated values to dependent widgets.
So, if you want to manage state using a ChangeNotifier, use ChangeNotifierProvider to integrate it seamlessly into your Flutter app!
MultiProvider in Flutter
In Flutter, MultiProvider is a powerful widget provided by the provider package. It allows you to combine multiple providers into a single widget tree. Here’s how it works:
Combining Multiple Providers:
Suppose you have different data models (e.g.,
ChatProvider,MessageProvider) that you want to use across your app.You can wrap your widget tree with a
MultiProviderand provide a list of providers. Each provider corresponds to a specific data model.For example:
MultiProvider( providers: [ ChangeNotifierProvider<ChatProvider>( create: (context) => ChatProvider(), ), ChangeNotifierProvider<MessageProvider>( create: (context) => MessageProvider(), ), // Add more providers as needed ], child: YourApp(), )
Accessing Providers:
Once you’ve set up the
MultiProvider, you can access the provided data models usingProvider.of<T>(context).For instance, in your widget, you can use:
final chatProvider = Provider.of<ChatProvider>(context); final messageProvider = Provider.of<MessageProvider>(context);
Context Hierarchy:
The context hierarchy matters. Providers should be above the widgets that need access to them.
If you want to use providers across different routes, place the
MultiProviderabove yourMaterialApp.However, having multiple
MaterialAppwidgets is not recommended. Instead, consider passing the providers as values to new routes without nesting additionalMaterialAppwidgets.
Best Practices for organising provider setup:
Certainly! Organising your Provider setup effectively is crucial for maintaining a clean and scalable Flutter app. here are some best practices:
Separate Concerns:
Divide your code into logical layers: UI, business logic, and data.
Place UI-related widget in separate files(e.g.,
screens,widgetsfolders).Keep business logic (providers)in their own files(e.g.,
providersfolder)
Provider Classes:
Create separate provider classes for different data models or features.
For example, if you have tasks and user authentication, create
TaskProviderandAuthProvider.
Nested Providers:
Use nested providers when one provider depends on another.
For instance, if a
TaskListwidget needs access to both tasks and user data, nestTaskProviderandAuthProvider.
Provider Tree:
Visualise your provider tree. Understand which widgets depend on which providers.
Avoid unnecessary providers at the root level. Only expose what's needed.
Scoped Providers:
Use
Provider.oforConsumerfor specific widgets that need access to a provider.Avoid using
Provider.ofat the root level unless it's truly global state.
Provider Architecture:
Consider using a layered architecture(e.g., Clean Architecture)with providers.
Separate data sources (API, local storage) from business logic providers.
Value vs. ChangeNotifier:
Use
ChangeNotifierProviderfor mutable state(e.g.,tasks, user preferences).Use
Provider.valuefor immutable data (e.g., constants, configuration).
Dispose Resources:
Clean up resources(e.g.,close streams, cancel subscriptions) in your provider's
disposemethod.Avoid memory leaks.
Testing:
Write unit tests for your providers.
Use
ProviderScopein your tests to isolate providers.
Localisation and Themes:
- Consider using providers for localisation (language) and themes (dark mode, light mode).
Using the Provider package for state management in Flutter offers a scalable solution for managing application state. By leveraging
ChangeNotifierProviderand other provider classes, developers can efficiently handle state changes and ensure their apps remain maintainable and testable. Organising your provider setup with best practices, such as separating concerns and using nested providers, enhances the structure and readability of your code. Whether managing simple state or complex data models, Provider simplifies the process, making it an essential tool for any Flutter developer.





