Paramclasses Academy - Blog

Tutorials Details

←
Post 22 of 40
→

Provider State Management in Flutter: A Beginner’s Tutorial

Provider State Management in Flutter: A Beginner’s Tutorial

November 2, 2026

❖ Provider State Management in Flutter: A Beginner’s Tutorial

❖ Welcome to Param Classes!

In Flutter, state management helps you store, update and share application data. In the previous tutorial, you learned how to use setState() to update the user interface.

But what happens when multiple screens or widgets need the same data?

For example, imagine an e-commerce application:

  • The Home screen displays products.

  • The Product Details screen adds products to the cart.

  • The Cart screen displays the selected products.

  • The Profile screen displays user information.

If multiple widgets need access to the same data, managing everything with local setState() can become difficult.

Flutter developers often use Provider to manage and share application state more easily.

In this tutorial by Param Classes, you will learn how to install Provider, understand ChangeNotifier, use ChangeNotifierProvider and Consumer, and build a practical counter application.

✦ 1. What Is Provider in Flutter?

Provider is a popular state management solution used in Flutter applications.

It helps developers share data between widgets without passing the same information manually through every widget.

For example, suppose you have a shopping cart application. Instead of storing separate cart information in different screens, you can maintain the cart data in one shared class.

Other widgets can access that data and display updated information.

Main benefits of Provider:

  • Share data between multiple widgets.

  • Keep business logic separate from UI code.

  • Reduce unnecessary manual data passing.

  • Organize application state.

  • Make applications easier to maintain.

Provider is available as a Flutter package.

Official package: https://pub.dev/packages/provider

✦ 2. Install Provider in Flutter

Before using Provider, you need to add the package to your Flutter project.

Step 1: Open your Flutter project

Open your project in Android Studio or VS Code.

Step 2: Open the terminal

Run this command:

flutter pub add provider

This command adds the Provider dependency to your pubspec.yaml file.

Step 3: Import the package

Whenever you need Provider classes, import:

import 'package:provider/provider.dart';

Now you can use Provider widgets and classes in your application.

✦ 3. Understand ChangeNotifier

ChangeNotifier is a class provided by Flutter's foundation library. It allows an object to notify its listeners when its data changes.

In Provider-based applications, developers commonly use ChangeNotifier to manage application state.

For example, suppose you have a counter variable.

When the counter changes, you can call:

notifyListeners();

This notifies registered listeners that the data has changed.

Basic ChangeNotifier Example:

import 'package:flutter/material.dart';

class CounterProvider extends ChangeNotifier {

  int counter = 0;

  void increaseCounter() {
    counter++;
    notifyListeners();
  }

  void decreaseCounter() {
    if (counter > 0) {
      counter--;
      notifyListeners();
    }
  }

  void resetCounter() {
    counter = 0;
    notifyListeners();
  }
}

Explanation:

  • CounterProvider is a class that manages counter data.

  • extends ChangeNotifier allows the class to notify listeners.

  • counter stores the current value.

  • increaseCounter() increases the counter.

  • decreaseCounter() decreases the counter.

  • resetCounter() resets the value.

  • notifyListeners() informs listening widgets about the changes.

Notice that the counter logic is separate from the user interface.

✦ 4. Understand ChangeNotifierProvider

Creating a ChangeNotifier class is not enough. You also need to make it available to the widgets that require its data.

This is where ChangeNotifierProvider is used.

It creates and provides an instance of your ChangeNotifier class to its descendant widgets.

Basic Example:

ChangeNotifierProvider(
  create: (context) => CounterProvider(),
  child: const MyHomePage(),
)

Explanation:

  • ChangeNotifierProvider provides the state object.

  • create creates an instance of CounterProvider.

  • child contains the widget tree that can access the provider.

You can place it above your application screens so that multiple screens can access the same state.

✦ 5. Understand Consumer Widget

The Consumer widget listens to a Provider and rebuilds its builder when the provided object notifies its listeners.

For example:

Consumer<CounterProvider>(
  builder: (context, provider, child) {
    return Text(
      "Counter: ${provider.counter}",
    );
  },
)

Explanation:

  • Consumer<CounterProvider> listens to CounterProvider.

  • builder builds the user interface.

  • provider gives access to the provided object.

  • provider.counter reads the current counter value.

When notifyListeners() is called, the Consumer rebuilds to show the updated value.

✦ 6. Build a Complete Counter App Using Provider

Now let's combine everything to create a practical Flutter application.

Our application will contain:

  • Increase button.

  • Decrease button.

  • Reset button.

  • Counter value.

  • Provider-based state management.

Step 1: Create the Provider Class

Create a new file inside the lib folder:

counter_provider.dart

Add this code:

import 'package:flutter/material.dart';

class CounterProvider extends ChangeNotifier {

  int counter = 0;

  void increaseCounter() {
    counter++;
    notifyListeners();
  }

  void decreaseCounter() {
    if (counter > 0) {
      counter--;
      notifyListeners();
    }
  }

  void resetCounter() {
    counter = 0;
    notifyListeners();
  }
}

This file manages the counter value and its update methods.

Step 2: Configure Provider in main.dart

Open main.dart and add the following code:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import 'counter_provider.dart';
import 'home_page.dart';

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => CounterProvider(),
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomePage(),
    );
  }
}

Here, ChangeNotifierProvider makes CounterProvider available to the application widgets below it.

Step 3: Create the Home Screen

Create another file:

home_page.dart

Add this code:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import 'counter_provider.dart';

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: const Text("Provider Counter App"),
      ),

      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [

            Consumer<CounterProvider>(
              builder: (context, provider, child) {
                return Text(
                  "Counter: ${provider.counter}",
                  style: const TextStyle(
                    fontSize: 30,
                    fontWeight: FontWeight.bold,
                  ),
                );
              },
            ),

            const SizedBox(height: 25),

            ElevatedButton(
              onPressed: () {
                context
                    .read<CounterProvider>()
                    .increaseCounter();
              },
              child: const Text("Increase"),
            ),

            ElevatedButton(
              onPressed: () {
                context
                    .read<CounterProvider>()
                    .decreaseCounter();
              },
              child: const Text("Decrease"),
            ),

            ElevatedButton(
              onPressed: () {
                context
                    .read<CounterProvider>()
                    .resetCounter();
              },
              child: const Text("Reset"),
            ),

          ],
        ),
      ),
    );
  }
}

✦ Step 4: Run Your Application

Open the terminal and execute:

flutter run

You should see a counter application with three buttons.

Try these actions:

  1. Tap Increase to increase the counter.

  2. Tap Decrease to reduce the counter.

  3. Tap Reset to set the counter back to zero.

The displayed value updates when the Provider notifies its listeners.

✦ 7. Understand context.read() and context.watch()

Provider offers different ways to access shared data.

Two commonly used methods are context.read() and context.watch().

A. context.read()

Use context.read() when you want to access a Provider without subscribing the current widget to its changes.

Example:

context.read<CounterProvider>().increaseCounter();

This is useful inside button callbacks when you only want to call a method.

B. context.watch()

Use context.watch() when the widget needs to listen for changes and rebuild when the provided object changes.

Example:

final counter = context.watch<CounterProvider>().counter;

You can then display the value:

Text("Counter: $counter")

Difference:

Method Purpose
context.read() Access data without listening
context.watch() Access data and listen for changes
Consumer Rebuild a specific section when notified

Choose the method according to the part of the interface that needs to respond to state changes.

✦ 8. Provider vs setState()

Both setState() and Provider can manage application state, but they are useful in different situations.

Feature setState() Provider
Basic usage Local widget state Shared application state
Setup Simple Requires package and provider setup
Data sharing Usually through widget structure Across descendant widgets
Code organization State often stays in widget State can be separated into classes
Best for Small UI changes Shared or more complex state

When should you use setState()?

Use it for simple changes such as:

  • Changing a button color.

  • Showing or hiding a widget.

  • Managing a small counter.

  • Toggling password visibility.

When should you use Provider?

Consider Provider when:

  • Multiple screens need the same data.

  • You want to separate UI and business logic.

  • You are managing shared application information.

  • Passing data through several widget levels becomes difficult.

Provider is not automatically necessary for every Flutter project. Choose the simplest solution that meets your application's requirements.

✦ 9. Common Mistakes Beginners Should Avoid

1. Forgetting notifyListeners()

If you update a variable but do not call notifyListeners(), listening widgets will not be notified about that change.

2. Missing the Provider Package

Make sure Provider is added to pubspec.yaml before importing it.

3. Using Provider Outside Its Scope

A widget can only access a Provider that exists above it in the widget tree.

4. Using read() When You Need Updates

If a widget needs to rebuild when data changes, use watch() or Consumer instead of only read().

5. Keeping All Logic in the UI

Separate application state and business logic into appropriate classes to keep your code organized.

✦ 10. Practice Tasks for Beginners

After completing this tutorial, try these exercises:

  1. Create a counter application using Provider.

  2. Build a Like button with a changing heart icon.

  3. Create a shopping cart counter.

  4. Add a Reset button to a Provider-based application.

  5. Create a theme switcher using ChangeNotifier.

  6. Build a small student management screen where multiple widgets display shared student information.

These practical tasks will help you understand how Provider works in real Flutter applications.

❖ Conclusion

Provider is a useful state management solution for Flutter developers. It helps share application data between widgets and keeps state management logic separate from the user interface.

In this tutorial, you learned how to install Provider, create a ChangeNotifier class, use ChangeNotifierProvider, display data with Consumer, and access state using context.read() and context.watch().

You also built a complete counter application using Provider.

At Param Classes, our goal is to help beginners learn Flutter through practical coding examples and real-world projects. Start with simple applications, practice Provider concepts and gradually build more advanced mobile apps.

Learn Today, Grow Tomorrow with Param Classes!

←
Post 22 of 40
→