Yesterday my friend said something like "Iâm writing simple offline app, I donât need these streams and all that jazz". I was confused, but I thought, that there may be other coders in this delusion.
Below, literally in 50 lines I will show, on known example that reactivity is:
a) not about offline/online
b) very easy
c) very good for simplifying almost any code
To my hasty critics,
who rush into battle without looking back, supposing that BlocProvider
â is a provider, I'd recommended to read first the basic article for general development. The reference to an article is on page of flutter_bloc, at first line in description.
A well-known to all example is âA counterâ, which generated when the Flutter project is created, is the good start point for demonstration a lot of practices. So, it contains MyHomePage extends StatefulWidget
, method _incrementCounter
for incrementâs command and setState
for redraw entire hierarchy of widgets.
Let's introduce reactivity with the help of rxdart
library and some easy steps:
Letâs add a library in pubspec.yaml
dependencies:
...
rxdart: 0.22.2
Letâs change a counterâs architecture and add event
class _Counter {
int _count;
int get count => _count;
_Counter(this._count)
: this.onCounterUpd = BehaviorSubject<int>.seeded(_count);
/// Here is the event.
final BehaviorSubject<int> onCounterUpd;
/// Increment now fires an event.
Future incrementCounter() async {
onCounterUpd.add(++_count);
}
}
final _counter = _Counter(5);
Letâs make class StatelessWidget
class MyHomeRxPage extends StatelessWidget {
final title;
/// ! Look it can be constant one now.
const MyHomeRxPage({Key key, this.title}) : super(key: key);
...
Letâs wrap up a widget in a StreamBuilder and change a call of incrementâs method.
StreamBuilder<int>(
stream: _counter.onCounterUpd,
builder: (context, snapshot) {
return Text(
'${snapshot.data}',
style: Theme.of(context).textTheme.display1,
);
}),
...
floatingActionButton: FloatingActionButton(
onPressed: _counter.incrementCounter,
...
Thatâs all. In full it looks like that:
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:rxdart/rxdart.dart';
class _Counter {
int _count;
int get count => _count;
_Counter(this._count)
: this.onCounterUpd = BehaviorSubject<int>.seeded(_count);
/// event
final BehaviorSubject<int> onCounterUpd;
/// fire an event
Future incrementCounter() async {
onCounterUpd.add(++_count);
}
}
final _counter = _Counter(5);
class MyHomeRxPage extends StatelessWidget {
final title;
const MyHomeRxPage({Key key, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
StreamBuilder<int>(
stream: _counter.onCounterUpd,
builder: (context, snapshot) {
return Text(
'You have pushed the button ${snapshot.data} times:',
);
}),
// Text(
// 'You have pushed the button this many times:',
// ),
StreamBuilder<int>(
stream: _counter.onCounterUpd,
builder: (context, snapshot) {
return Text(
'${snapshot.data}',
style: Theme.of(context).textTheme.display1,
);
}),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _counter.incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), //
);
}
}
Now the code is reactive, laconic, free from unnecessary redraws and easily extensible. For example, if itâs necessary to change text of other widget, when the counter is changing, itâs enough to do follow:
StreamBuilder<int>(
stream: onCounterUpd,
builder: (context, snapshot) {
return Text(
'You have pushed the button ${snapshot.data} times:',
);
}),
// Text(
// 'You have pushed the button this many times:',
// ),
and voila!
For comparison try to do this with InheritedWidget
or with another pattern.
So, I hope, I showed that
- The reactivity is very easy. Much easier than
InheritedWidgets
,BlocProvider
, etc. - The reactivity isnât about offline/online. Itâs about architecture. In some simple case even mustnât to enter additional classes to use it.
- The reactivity is sympathetic UI, quick widening functional, elegant division of code on layers all type:
MVC, MVP, MVI, MVVM, MVU
â whatever you want.
â Code: (branch iter_0004_rxdart
)
Good luck in coding.