Reputation: 882
In flutter, we want to update the display on a regular basis. We can update the display when the value changes. However, the set value does not change in this case. Therefore, we do not know what to do as a trigger to update the display.
We changed from Stateless Widget to Stateful Widget. And we started the timer in initState() and canceled the timer in dispose(). We regularly call notifyListeners () on ScopedModel and are updating the drawing.
It works as expected. Unfortunately, it is not a beautiful way. It is hard to understand, it is annoying. Do not you know a better way? How should we do?
We will clarify our implementation example below. It is a minimal code.
xxxxx_widget.dart
import 'package:flutter/material.dart';
import 'package:pregnancy/scoped_model/xxxxx_model.dart';
import 'package:pregnancy/widgets/yyyyy_widget.dart';
import 'package:scoped_model/scoped_model.dart';
class XxxxxWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ScopedModel<XxxxxModel>(
model: XxxxxModel(),
child: YyyyyWidget(),
);
}
}
yyyyy_widget.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:pregnancy/scoped_model/xxxxx_model.dart';
import 'package:scoped_model/scoped_model.dart';
class YyyyyWidget extends StatefulWidget {
@override
YyyyyWidgetState createState() {
return new YyyyyWidgetState();
}
}
class YyyyyWidgetState extends State<YyyyyWidget> {
Timer _timer;
@override
void initState() {
_timer = Timer.periodic(
const Duration(milliseconds: 500),
(Timer t) {
XxxxxModel.of(context).notify();
},
);
super.initState();
}
@override
void dispose() {
_timer.cancel();
_timer = null;
super.dispose();
}
@override
Widget build(BuildContext context) {
return ScopedModelDescendant<XxxxxModel>(
builder: (context, child, model) {
var diff = model.datetime.difference(DateTime.now());
var hours = diff.inHours.remainder(Duration.hoursPerDay);
var minutes = diff.inMinutes.remainder(Duration.minutesPerHour);
var seconds = diff.inSeconds.remainder(Duration.secondsPerMinute);
return Text('${hours} hours ${minutes} minutes ${seconds} seconds');
},
);
}
}
xxxxx_model.dart
import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
class XxxxxModel extends Model {
static XxxxxModel of(BuildContext context) =>
ScopedModel.of<XxxxxModel>(context);
DateTime _datetime = DateTime.now().add(Duration(days: 1));
get datetime => _datetime;
set datetime(DateTime value) {
_datetime = value;
notifyListeners();
}
void notify() {
notifyListeners();
}
}
Upvotes: 2
Views: 2038
Reputation: 30103
You could use a StreamBuilder
that listens to an interval stream. It automatically manages the subscription.
Your model can provide the stream as a property.
Upvotes: 1