Stream provides you a sequence of data. It can become memory leaks, if you don't dispose them correctly.
Use tip: At first, you'll have to install Pulse-X package. Here's the installation tip.
Usage
Stream data management is difficult. With Pulse-X, you won't have to use StreamController or Stream, or listen to StreamController. Pulse-X provides you with PulseXStreamViewModel class that you can extend and PulseXStreamBuilder for reactive UI.
Now, we'll create a realtime clock project that uses Stream data with Pulse-X.
First, you'll need to install intl package to convert date format.
Then, start creating a TimerViewModel class like this.
class TimerViewModel extends PulseXStreamViewModel<String> { // specify stream data type
late Timer _timer;
final DateFormat formattedDate = DateFormat('h:mm:ss a'); // convert date format
void addDateTime() {
_timer = Timer.periodic(
const Duration(seconds: 1),
(timer) {
String currentTime = formattedDate.format(DateTime.now());
addValue(currentTime); // Pulse will automatically add data via sink
},
);
}
@override
void onDispose() {
_timer.cancel(); // cancel your timer or it'll probably make memory leak
}
}
See! You don't even use stream here. Because Pulse is handling Stream automatically.
Then, it's time to create TimerView class.
final amber500 = Colors.amber.shade500;
class TimerView extends StatefulWidget {
const TimerView({Key? key}) : super(key: key);
@override
State<TimerView> createState() => _TimerViewState();
}
class _TimerViewState extends State<TimerView> {
final timerViewModel = TimerViewModel(); // create timer view model
@override
void initState() {
super.initState();
timerViewModel.addDateTime(); // add stream data
}
@override
void dispose() {
timerViewModel.onDispose(); // dispose view model to cancel timer
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Timer'),
),
body: Center(
child: PulseXStreamBuilder( // for reactive UI
viewModel: timerViewModel,
builder: (_, viewModel, snapshot) { // three parameters -context,view model, snapshot
// you have to use snapshot to retrieve stream data
if (snapshot.hasData) {
return TimerLabel(time: snapshot.data.toString());
} else if (snapshot.hasError) {
return const Text('Something went wrong');
}
return CupertinoActivityIndicator(
radius: 20,
color: amber500,
);
},
),
),
);
}
}
class TimerLabel extends StatelessWidget {
const TimerLabel({Key? key, required this.time}) : super(key: key);
final String time;
@override
Widget build(BuildContext context) {
return Text(
time,
style: Theme.of(context).textTheme.displayLarge?.copyWith(
color: amber500,
),
);
}
}