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.