Reputation: 173
I am trying to make a simple timer to know how much time has passed from a date to a current date
but the problem I have is that the Text widget is only painted once but it does not update, and I would like the text to update every 1 second. And not have to refresh the page, is it possible to do that?
import 'package:flutter/material.dart';
class TimerPage extends StatefulWidget {
@override
_TimerPageState createState() => _TimerPageState();
}
class _TimerPageState extends State<TimerPage> {
@override
Widget build(BuildContext context) {
final start = DateTime(2020, 8, 10, 16, 30, 0);
final currentdate= DateTime.now();
final comparation = currentdate.difference(start);
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.symmetric(vertical: 20),
child: Center(
child: Column(
children: <Widget>[
Text("Start time: " + start.toString()),
Divider(),
Text(
"time elapsed = " + comparation.toString().substring(0, 7),
style: TextStyle(color: Color(0xff5abd8c), fontSize: 26),
)
],
)),
),
),
);
}
}
I try this:
Timer timer;
final start = DateTime(2020, 8, 17, 21, 30, 0);
final dateActual = DateTime.now();
Duration comparation = new Duration(hours: 0, minutes: 0, seconds: 0);
@override
void initState() {
timer = Timer.periodic(Duration(seconds: 1), (_) {
setState(() {
comparation = dateActual.difference(start);
print(comparation);
});
});
}
@override
void dispose() {
timer?.cancel();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.symmetric(vertical: 20),
child: Center(
child: Column(
children: <Widget>[
Text("Start time: " + start.toString()),
Divider(),
Text(
"time elapsed = " + comparation.toString().substring(0, 7),
style: TextStyle(color: Color(0xff5abd8c), fontSize: 26),
)
],
)),
),
),
);
}
}
Upvotes: 1
Views: 3321
Reputation: 17113
To do this, you want a Timer
from the dart:async
library, specifically a Timer.periodic
.
Instantiate one in initState
of your StatefulWidget
and cancel it in dispose
.
Timer.periodic
takes a callback that fires after every duration that's passed. Since your DateTime
difference calculation is already done in build
, you just need to trigger a rebuild with setState
.
Timer timer;
@override
void initState() {
timer = Timer.periodic(Duration(seconds: 1), (_) {
setState(() {});
});
}
@override
void dispose() {
timer?.cancel();
}
It's not possible to do this without rebuilding, at the very least, the Text
widget that's being changed. I don't think it's necessary since there isn't much in this build
method, but if you wanted to do that, you would have to extract all of the necessary time calculations, timer, and single Text
widget to its own StatefulWidget
, so that only the one widget that's necessary to be rebuilt, is rebuilt.
Ideally, you should also be doing the time calculations outside of the build
method, but it's not a huge deal in this case and you'll get something that works.
Upvotes: 3