Reactive Programming in Flutter

Santhosh Adiga U
4 min readMar 3, 2023

--

Reactive programming has gained popularity among developers in recent years, and with the increasing use of Flutter for mobile app development, it has become more important than ever to understand reactive programming with Flutter. In this article, we will explore what reactive programming is and how it works with Flutter, with examples of code.

What is Reactive Programming?

Reactive programming is a programming paradigm that focuses on the flow of data and how it changes over time. It is a declarative way of programming, where the developer specifies what should happen when data changes, rather than how it should happen. In reactive programming, data is treated as a stream of events that can be observed, transformed, and reacted to.

Reactive Programming in Flutter

Flutter is a reactive framework that is based on reactive programming principles. Flutter provides a set of reactive widgets that can be used to build reactive user interfaces. The reactive widgets in Flutter are based on the Stream API, which is a core part of Dart, the programming language used by Flutter.

Streams are a sequence of asynchronous events that can be observed and processed. In Flutter, streams are used to represent data that changes over time, such as user input, network requests, and data from databases. Streams can be transformed using a set of operations, such as map, filter, and reduce.

To use reactive programming in Flutter, you need to understand how to work with streams and how to use the reactive widgets that Flutter provides.

Example of Reactive Programming in Flutter

Let’s consider an example of a simple counter app that demonstrates reactive programming in Flutter. The app consists of a button that increments a counter when pressed, and a text widget that displays the current value of the counter.

To implement this app using reactive programming in Flutter, we need to use a stream to represent the counter value. We can create a stream using the StreamController class, which allows us to add events to the stream and listen to them.

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

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Counter App',
home: Counter(),
);
}
}

class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
final StreamController<int> _streamController = StreamController<int>();
int _counter = 0;

@override
void dispose() {
_streamController.close();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Counter App')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
SizedBox(height: 16),
ElevatedButton(
child: Text('Increment'),
onPressed: () {
_counter++;
_streamController.add(_counter);
},
),
],
),
),
);
}
}

In the code above, we create a StreamController object called _streamController that will be used to add events to the stream. We also create a variable called _counter that holds the current value of the counter.

In the build method, we create a column widget that contains a text widget that displays the current value of the counter, and a button widget that increments the counter and adds the new value to the stream when pressed.

To update the UI when the counter value changes, we can use the StreamBuilder widget that Flutter provides. The StreamBuilder widget listens to the stream and rebuilds the UI whenever a new event is added to the stream. We can use the snapshot argument that the StreamBuilder widget provides to access the latest value of the stream.

class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
final StreamController<int> _streamController = StreamController<int>();
int _counter = 0;

@override
void dispose() {
_streamController.close();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Counter App')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
StreamBuilder<int>(
stream: _streamController.stream,
initialData: _counter,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
return Text(
'${snapshot.data}',
style: Theme.of(context).textTheme.headline4,
);
},
),
SizedBox(height: 16),
ElevatedButton(
child: Text('Increment'),
onPressed: () {
_counter++;
_streamController.add(_counter);
},
),
],
),
),
);
}
}

In the code above, we replace the Text widget that displays the current value of the counter with a StreamBuilder widget. The stream property of the StreamBuilder widget is set to the stream that we created earlier. The initialData property is set to the initial value of the stream, which is the current value of the counter.

In the builder method of the StreamBuilder widget, we use the snapshot argument to access the latest value of the stream. We use the Text widget to display the latest value of the stream.

Conclusion

Reactive programming is a powerful programming paradigm that can make your Flutter apps more efficient and responsive. By using streams and reactive widgets, you can build reactive user interfaces that respond to user input and data changes in real-time. Understanding reactive programming with Flutter can be challenging, but with the examples and code provided in this article, you should be able to get started with building reactive Flutter apps.

--

--

Santhosh Adiga U
Santhosh Adiga U

Written by Santhosh Adiga U

Founder of Anakramy ., dedicated to creating innovative AI-driven cybersecurity solutions.

No responses yet