Flutter State Management using Provider (Beginner Friendly).
In this blog, we will explore how to manage state in a Flutter application using the Provider package, which is a popular and beginner-friendly approach.
In this guide, we’ll to learn how to manage state in a Flutter application using the Provider package, which is a popular and beginner-friendly approach.
State management is a crucial aspect of app development, as it helps in maintaining and updating the UI based on user interactions and data changes.
By the end, you'll Understand:
- What is state management in Flutter?
- Why use the Provider package for state management?
- How to implement state management using Provider in a simple Flutter app.
What is the State ?
- When you take a fresh new Flutter app, it has a default counter app that increments the counter value when you press the button. Here, the counter value is a piece of state that changes when you interact with the button.
- State refers to the data that can change over time in your application. It can be anything from user inputs, fetched data, or UI elements that need to be updated based on certain actions.

Two Types of State in Flutter
- Local State: This type of state is confined to a single widget. For example, the counter value in the default Flutter app is a local state.
- Global State: This type of state is shared across multiple widgets in the application. For example, user authentication status or theme settings that need to be accessed by various parts of the app.

Why not setState()
- Using setState() is suitable for small applications with minimal state management needs. However, as the application grows in complexity, managing state using setState() can lead to code that is hard to maintain and scale.
- It results in prop drilling, where you have to pass state down through multiple widget layers, making the code cumbersome and less readable.
- It can lead to performance issues, as unnecessary widget rebuilds may occur when the state changes.
Example to illustrate prop drilling:
class AppLevel extends StatelessWidget {
@override
Widget build(BuildContext context) {
String text = "Prop Drilling Example";
return MaterialApp(
home: Level1(data : text),
);
}
}
class Level1 extends StatelessWidget {
final String data;
Level1({required this.data});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Level2(data: data),
);
}
}
class Level2 extends StatelessWidget {
final String data;
Level2({required this.data});
@override
Widget build(BuildContext context) {
return Center(
child: Level3(data : data),
);
}
}
class Level3 extends StatelessWidget {
final String data;
Level2({required this.data});
@override
Widget build(BuildContext context) {
return Center(
child: Text(data),
);
}
}

In above example if we have to pass data from AppLevel to Level2 we have to pass it through Level1 this is called prop drilling which can be avoided using state management solutions like Provider.
Solve with Provider
- Provider is a popular state management solution in Flutter that simplifies the process of managing and sharing state across the application.
- Instead of passing data through multiple widget layers, Provider allows you to create a centralized state that can be accessed by any widget in the widget tree.

In above diagram, the AppLevel widget provides the state using Provider, and Level3 can directly access the state without needing to go through Level1 and Level3.
Setting up Provider in a Flutter App
- Add the Provider package to your pubspec.yaml file:
pub add provider- Create a data model class that extends ChangeNotifier:
import 'package:flutter/foundation.dart';
class Data extends ChangeNotifier {
String text = "Provider Example";
}- Wrap your main app with ChangeNotifierProvider to provide the state to the widget tree:
import 'package:provider/provider.dart';
void main() {
runApp(
ChangeNotifierProvider<Data>(
create: (context) => Data(),
child: MyApp(),
),
);
}- Access the state in any widget using Provider.of or Consumer:
class Level3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
String data = context.watch<Data>().text;
return Center(
child: Text(data),
);
}
}Difference Between Watch and Read
context.watch<T>(): This method listens for changes in the provided data of type T. When the data changes, the widget that calls this method will rebuild to reflect the updated state.context.read<T>(): This method retrieves the provided data of type T without listening for changes. It is typically used when you want to access the data once, such as in event handlers, without causing the widget to rebuild on data changes.
Conclusion
Using Provider for state management in Flutter simplifies the process of sharing and managing state across your application.
It helps avoid prop drilling, improves code maintainability, and enhances performance by reducing unnecessary widget rebuilds.
As your application grows, adopting a state management solution like Provider becomes essential for building scalable and efficient Flutter apps.
Recommended for you
Jan 31, 2026
Custom Animation in Flutter
Learn how to implement custom animations in Flutter to enhance user experience with smooth transitions and engaging effects.
Jan 25, 2026
Setting Up Android App widget in Flutter.
In this blog post, I will guide you through the steps to set up home_widget in your Flutter application, enabling you to create interactive home screen widgets for Android.