Introduction
When building mobile apps using Flutter, managing state is one of the most important concepts to understand. State simply means the data that changes over time, such as user input, API responses, or UI updates.
If state is not managed properly, your app can become difficult to maintain, buggy, and hard to scale. This is where state management solutions like Provider come in.
Provider is one of the most popular and beginner-friendly state management techniques in Flutter. It helps you manage and share data across your app efficiently.
In this article, we will learn how to manage state in Flutter using Provider step by step with simple explanations and practical examples.
What is State in Flutter?
In Flutter, state refers to any data that can change during the lifecycle of the app.
Examples:
Counter value
User login status
API data
Theme changes
There are two types of state:
Local State → Managed within a single widget
Global State → Shared across multiple widgets
Provider is mainly used for managing global state.
What is Provider in Flutter?
Provider is a wrapper around InheritedWidget that makes state management easier and more efficient.
It allows you to:
Store data in one place
Access data anywhere in the widget tree
Update UI automatically when data changes
Why Use Provider for State Management?
Provider is widely used because:
Simple and easy to learn
Lightweight and efficient
Reduces boilerplate code
Works well with Flutter architecture
Step 1: Add Provider Dependency
First, add the Provider package to your project.
dependencies:
provider: ^6.0.0
Then run:
flutter pub get
Step 2: Create a Model Class
Create a class that holds your state.
import 'package:flutter/material.dart';
class CounterModel extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
Explanation:
ChangeNotifier → notifies UI when data changes
notifyListeners() → rebuilds widgets
Step 3: Provide the Model to the App
Wrap your app with ChangeNotifierProvider.
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => CounterModel(),
child: MyApp(),
),
);
}
This makes the state available across the app.
Step 4: Access State in UI
Use Consumer or Provider.of to access data.
Example using Consumer:
Consumer<CounterModel>(
builder: (context, counter, child) {
return Text('Count: ${counter.count}');
},
)
This rebuilds UI when count changes.
Step 5: Update State from UI
Call methods from the model.
ElevatedButton(
onPressed: () {
Provider.of<CounterModel>(context, listen: false).increment();
},
child: Text('Increment'),
)
This updates the state and UI automatically.
Step 6: Using Provider.of vs Consumer
Provider.of → Direct access
Consumer → Rebuilds only required widgets
Best practice:
Use Consumer for UI updates
Use Provider.of for actions
Step 7: Organizing Code Structure
For larger apps:
models/ → state classes
providers/ → business logic
screens/ → UI
This keeps code clean and maintainable.
Step 8: Using MultiProvider
When using multiple providers:
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CounterModel()),
ChangeNotifierProvider(create: (_) => AnotherModel()),
],
child: MyApp(),
)
This helps manage multiple states easily.
Step 9: Avoid Common Mistakes
Forgetting notifyListeners()
Using listen: true in wrong places
Rebuilding entire UI unnecessarily
Real-World Example
Use Provider for:
Shopping cart state
User authentication
Theme switching
API data handling
Best Practices for Provider
Keep models simple
Separate UI and logic
Use Consumer for performance
Avoid deeply nested providers
Summary
Provider is a powerful and simple state management solution in Flutter. By using ChangeNotifier, Consumer, and proper structure, you can manage app state efficiently and build scalable applications. Following a step-by-step approach helps you understand how data flows and how UI updates automatically, making your Flutter development smoother and more maintainable.

Join the conversation! Your thoughts help the community grow.