Mobile Development 24 min read

Flutter State Management: Using Provider and Source Code Analysis

This article explains how to use the Provider package for state management in Flutter, detailing its implementation, including ChangeNotifierProvider, Consumer, ProxyProvider, and the underlying InheritedWidget mechanism, and compares it with other popular Flutter state‑management solutions.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Flutter State Management: Using Provider and Source Code Analysis

Flutter's state management is crucial for building maintainable and performant applications. This article introduces the Provider package, which is officially recommended by Google, and demonstrates how to share data across widgets using ChangeNotifierProvider, Consumer, and ProxyProvider.

Basic usage : Create a model that mixes in ChangeNotifier , expose mutable state, and call notifyListeners() when the state changes. Then wrap the widget tree with ChangeNotifierProvider to make the model available to descendants.

class ProviderViewModel with ChangeNotifier {
  int _number = 0;
  get number => _number;
  void addNumber() {
    _number++;
    notifyListeners();
  }
}

Wrap the UI with the provider and access the model using Provider.of<ProviderViewModel>(context) or the newer context.watch<ProviderViewModel>() and context.read<ProviderViewModel>() APIs.

class ProviderTestPage extends StatelessWidget {
  final _providerViewModel = ProviderViewModel();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Provider Test")),
      body: ChangeNotifierProvider.value(
        value: _providerViewModel,
        builder: (context, child) {
          return Column(
            children: [
              const Text("I am the parent"),
              Text("Parent number is: \\${Provider.of<ProviderViewModel>(context).number}"),
              ChildA(),
            ],
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.add),
        onPressed: () { _providerViewModel.addNumber(); },
      ),
    );
  }
}

When the button is pressed, addNumber() updates the model and triggers a rebuild of all widgets that depend on it. The Consumer<ProviderViewModel> widget can be used for more granular updates, rebuilding only the part of the UI that reads the model.

class ChildC extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      color: Colors.blue,
      child: Column(
        children: [
          const Text("I am a child"),
          Consumer<ProviderViewModel>(builder: (context, value, child) {
            print("ChildC Consumer builder");
            return Text("Child C number: \\${value.number}");
          }),
          MaterialButton(
            child: const Text("Add Number"),
            color: Colors.white,
            onPressed: () { context.read<ProviderViewModel>().addNumber(); },
          ),
        ],
      ),
    );
  }
}

ProxyProvider allows one model to depend on another. The example defines ProxyProviderViewModel that receives the current value of ProviderViewModel and updates its own state accordingly.

class ProxyProviderViewModel with ChangeNotifier {
  int number;
  ProxyProviderViewModel(this.number);
  String get title => "The number is: \\${number}";
}
class ProxyProviderTestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Provider Test")),
      body: MultiProvider(
        providers: [
          ChangeNotifierProvider<ProviderViewModel>(create: (_) => ProviderViewModel()),
          ChangeNotifierProxyProvider<ProviderViewModel, ProxyProviderViewModel>(
            create: (context) => ProxyProviderViewModel(context.read<ProviderViewModel>().number),
            update: (context, providerViewModel, proxyProviderViewModel) =>
                ProxyProviderViewModel(providerViewModel.number),
          ),
        ],
        builder: (context, child) {
          return Column(
            children: [
              ChildProxy(),
              MaterialButton(
                child: const Text("Add Number"),
                color: Colors.amberAccent,
                onPressed: () { context.read<ProviderViewModel>().addNumber(); },
              ),
            ],
          );
        },
      ),
    );
  }
}

InheritedWidget principle : Provider is built on top of InheritedWidget . An InheritedWidget holds shared data and notifies dependent widgets when updateShouldNotify returns true. Dependent widgets register themselves via context.dependOnInheritedWidgetOfExactType , which adds the dependent to the parent’s _dependents set. When the data changes, the parent calls notifyDependents , causing each dependent to run didChangeDependencies and rebuild.

The article walks through the internal Flutter classes involved ( InheritedElement , InheritedContext , InheritedProviderScope , etc.) to show how Provider registers listeners on a ChangeNotifier and propagates updates through the widget tree.

Consumer widget simply calls Provider.of<T>(context) inside its builder, ensuring that only the subtree wrapped by Consumer is registered as a dependent, which enables fine‑grained rebuilds.

Finally, the article compares Provider with other popular Flutter state‑management solutions (e.g., Riverpod, Bloc, GetX) and provides guidance on choosing the appropriate approach based on project size and team preferences.

References :

https://www.cnblogs.com/mengqd/p/14300373.html

https://www.jianshu.com/p/bf2f33b2b5ef

Flutterstate managementConsumerProviderInheritedWidgetChangeNotifierProxyProvider
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.