State Management in Flutter

Chanidu Madalagama
4 min readFeb 3, 2023

--

Flutter state management examples

Flutter is a popular open-source framework for building cross-platform applications with a focus on high performance and visually appealing UI. As applications become more complex, state management can become a challenge. In this article, we will discuss the various state management techniques available in Flutter and provide examples to help you understand how to use them effectively in your applications.

What is State Management?

State management refers to the process of managing the data or state of an application. It involves managing the data that changes over time and needs to be displayed or updated in the UI. The goal of state management is to make it easier to maintain the application’s state and to ensure that it is consistent across the application.

State Management Techniques in Flutter

There are several techniques for managing state in Flutter, including:

  1. Scoped Model

Scoped Model is a state management technique that allows you to share a common model across multiple widgets in the widget tree. It uses a single instance of a model to store the application state, and the model is accessible to any widget that needs it. To use Scoped Model, you need to create a model class that extends the ScopedModel class, and then use the ScopedModelDescendant widget to access the model in your widgets.

Example:

class CounterModel extends Model {
int _counter = 0;

int get counter => _counter;

void incrementCounter() {
_counter++;
notifyListeners();
}
}

class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ScopedModel(
model: CounterModel(),
child: Scaffold(
appBar: AppBar(
title: Text('Scoped Model Example'),
),
body: ScopedModelDescendant<CounterModel>(
builder: (context, child, model) {
return Center(
child: Text(
'Counter: ${model.counter}',
style: TextStyle(fontSize: 24.0),
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
ScopedModel.of<CounterModel>(context).incrementCounter();
},
child: Icon(Icons.add),
),
),
);
}
}

2. Provider

The provider is a state management technique that uses a widget tree to share data across widgets. It is a generic implementation of the Scoped Model technique and is designed to make it easier to use. To use Provider, you need to create a provider class and then use the Provider.of method to access the provider in your widgets.

Example:

class CounterProvider with ChangeNotifier {
int _counter = 0;

int get counter => _counter;

void incrementCounter() {
_counter++;
notifyListeners();
}
}

class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => CounterProvider(),
child: Scaffold(
appBar: AppBar(
title: Text('Provider Example'),
),
body: Center(
child: Consumer<CounterProvider>(
builder: (context, provider, child) {

3. BLoC (Business Logic Component)

BLoC is a state management technique that separates the presentation logic from the business logic. It uses streams to communicate data between the two components, allowing you to update the UI in response to changes in the data. To use BLoC, you need to create a BLoC class that implements the StreamController, and then use the StreamBuilder widget to access the streams in your widgets.

Example:

class CounterBloc {
final _counterController = StreamController<int>();
Stream<int> get counterStream => _counterController.stream;
int _counter = 0;

void incrementCounter() {
_counter++;
_counterController.sink.add(_counter);
}

void dispose() {
_counterController.close();
}
}

class MyHomePage extends StatelessWidget {
final _bloc = CounterBloc();

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BLoC Example'),
),
body: Center(
child: StreamBuilder<int>(
stream: _bloc.counterStream,
initialData: 0,
builder: (context, snapshot) {
return Text(
'Counter: ${snapshot.data}',
style: TextStyle(fontSize: 24.0),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_bloc.incrementCounter();
},
child: Icon(Icons.add),
),
);
}

@override
void dispose() {
_bloc.dispose();
super.dispose();
}
}

4. Inherited Widget

Inherited Widget is a state management technique that allows you to pass data down the widget tree. To use Inherited Widget, you need to create a custom Inherited Widget and then use the InheritedWidget.of method to access the data in your widgets.

Example:

class CounterInheritedWidget extends InheritedWidget {
final int counter;

CounterInheritedWidget({
Key key,
this.counter,
Widget child,
}) : super(key: key, child: child);

static CounterInheritedWidget of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<CounterInheritedWidget>();
}

@override
bool updateShouldNotify(CounterInheritedWidget oldWidget) {
return counter != oldWidget.counter;
}
}

class MyHomePage extends StatelessWidget {
final int counter;

MyHomePage({
Key key,
this.counter,
}) : super(key: key);

@override
Widget build(BuildContext context) {
return CounterInheritedWidget(
counter: counter,
child: Scaffold(
appBar: AppBar(
title: Text('Inherited Widget Example'),
),
body: Center(

In conclusion, there are various state management techniques in Flutter, each with its own pros and cons. Some of the most popular state management techniques are Provider, ScopedModel, BLoC, and InheritedWidget. Each of these techniques can be used for different use cases, and the choice of which to use will depend on the requirements of your project.

It’s important to note that there is no one-size-fits-all solution for state management in Flutter, and you may find yourself using a combination of these techniques to achieve the desired result. The important thing is to understand the different options available to you and make an informed decision on the best approach for your project.

In the end, state management is an essential part of building Flutter applications, and understanding the various techniques available will help you write better, more maintainable code.

--

--

Chanidu Madalagama

A dedicated and diligent young individual who’s driven by a thirst for challenge. I have more than 1 year working experience as a Mobile Application developer.