I'm building an app with Flutter and I need to show a clock that includes milliseconds
Here's what I have so far. It works, but only shows seconds.
#override
void initState() {
_timeString = DateFormat('hh:mm:ss').format(DateTime.now());
Timer.periodic(Duration(milliseconds: 50), (Timer t) => _getTime());
super.initState();
}
void _getTime() {
final String formattedDateTime =
DateFormat('hh:mm:ss').format(DateTime.now());
setState(() {
_timeString = formattedDateTime;
});
}
If anyone is interested, using 'hh:mm:ss:SS' is enough.
Related
I am trying to make a simple timer which run till a given time. This is how I have tried to call the timer function. It gives the error as mentioned in the title. I believe the error is there because I am calling set state method in the init state, but I really need to make this functionality that, when this widget enters the screen, a timer begins and do something when the timer ends. Any help is greatly appreciated.
late double timeRemaining;
late Timer _timer;
void startTimer(double timeRemaing) {}
#override
void initState() {
timeRemaining =
widget.startDate.difference(widget.endDate).inSeconds / 1000 - 80;
const Duration seconds = Duration(seconds: 1);
_timer = Timer.periodic(seconds, (timer) {
setState(() {
timeRemaining--;
if (timeRemaining <= 0) {
// done = true;
done = true;
timer.cancel();
}
});
});
super.initState();
}
as the title says, you're building widget during another build (when you call setState in the timer).So the solution is to wait for the widget to finish building, then start your timer, this can be done by using addPostFrameCallback, like the following:
#override
void initState() {
timeRemaining =
widget.startDate.difference(widget.endDate).inSeconds / 1000 - 80;
const Duration seconds = Duration(seconds: 1);
// this will schedule a callback for the end of this frame.
WidgetsBinding.instance.addPostFrameCallback((_) {
_timer = Timer.periodic(seconds, (timer) {
setState(() {
timeRemaining--;
if (timeRemaining <= 0) {
// done = true;
done = true;
timer.cancel();
}
});
});
});
super.initState();
}
try it and tell me if this works
I have 2 function that call NTP to get local date time. First one is working like a clock using Timer.periodic and the second one for get the time when user tapped the button. But when I display the time in the second function its still runing the Timer.periodic. How to avoid that? Thanks
My Code:
Future<String> getNTPTime() async {
DateTime startDate = await NTP.now();
String currentDate = DateFormat('d MMMM yyyy').format(startDate);
String currentTime = DateFormat('kk : mm : ss').format(startDate);
print('NTP DateTime: $startDate');
if (mounted) {
setState(() {
_currentDate = currentDate;
_currentTime = currentTime;
});
}}
Future<String> getNTPTimeIn() async {
DateTime ntpTimeIn = await NTP.now();
String timeIn = DateFormat('kk : mm : ss').format(ntpTimeIn);
print('NTP DateTime: $ntpTimeIn');
if (mounted) {
setState(() {
_ntpTimeIn = timeIn;
});
}}
and call it in the initState
#override
super.initState();
getNTPTime();
Timer.periodic(Duration(seconds: 1), (timer) => getNTPTime());
}
when I display the _ntpTimeIn the Timer.periodic is still running.
This is how you should implement it.
class YourClas extends StatefulWidget{
Timer _timer;
#override
void initState(){
super.initState();
getNTPTime();
_timer = Timer.periodic(Duration(seconds: 1), (timer) => getNTPTime());
}
#override
void dispose(){
if(_timer.isActive) _timer.cancel();
super.dispose();
}
}
Then when user taps the button call _timer.cancel(); to stop the Timer
I've created an app using flutter and I want to get start a timer when the user navigates to a screen to calculate how long will he stay there.
I want if he has completed three minutes on the screen to print anything.
I don't have any ideas about the timer or how to use it.
please help me regarding achieving that.
thanks all.
You can do something like that.
Timer _timer;
#override
void initState() {
_timer = Timer(Duration(milliseconds: 500), () {
// SOMETHING
});
super.initState();
}
#override
void dispose() {
if (_timer != null) {
_timer.cancel();
_timer = null;
}
super.dispose();
}
Please have a look of this:
import 'dart:async';
main() {
const twentyMillis = const Duration(milliseconds:20);
new Timer(twentyMillis, () => print('hi!'));
}
Also look Timer class link
So I'm using the Sparkline library for flutter to create a line chart and it works when I use a static list Eg. ([0, 10, 20, 20, 30]). But I want to make it so that at every say 10 seconds it would add a value, for now that could be anything but later i want to pull that value from firebase.
I've looked at other examples of people trying to run a function multiple time init state but it isnt working. I know I need to redraw the widget but I don't think I'm doing it right or I'm missing something.
class BikeState extends State<BikeScreen> {
Timer timer;
List<double> speedList = new List();
Sparkline speedChart1 = Sparkline(data: [0],);
void updateChart(Timer timer){
speedChart1 = Sparkline(data: speedList,);
speedList.add(10);
speedChart1 = Sparkline(data: speedList,);
}
#override
void initState() {
super.initState();
timer = Timer.periodic(Duration(seconds: 15), updateChart);
}
#override
void dispose() {
timer?.cancel();
super.dispose();
}
All that happens when i run it is that I get the just the graph which has the values passed into it when it was declared and nothing was changed.
Flutter will not repaint or rebuild any widgets for you on its own. In your case you already have a stateful widget, which is the correct way, but you also need to tell flutter that your state has changed. This is done by using the setState method like this:
void updateChart(Timer timer) {
setState(() {
speedChart1 = Sparkline(data: speedList,);
speedList.add(10);
speedChart1 = Sparkline(data: speedList,);
});
}
Additionally, depending on how your build method looks, I think you should remove the Sparkline Widget from your state and have it purely during build like this:
class BikeState extends State<BikeScreen> {
Timer timer;
List<double> speedList = new List();
void updateChart(Timer timer){
setState(() {
speedList.add(10);
});
}
#override
void initState() {
super.initState();
timer = Timer.periodic(Duration(seconds: 15), updateChart);
}
#override
void dipose() {
timer?.dipose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Sparkline(data: speedList);
}
}
When my app's game screen appears, an audio file starts playing that says "Ready? 3...2...1...GO" and then plays music.
I'd like the game timer to start at the same time that it says "GO", which is exactly 4 seconds into the audio.
I got pretty close by starting the audio file in initState() and then using "Future.delayed(const Duration(seconds: 4), () => startTimer());" but the problem is that the first time a user plays, it take a bit of time for the audio to load, so then the timer starts before the audio says "GO".
I tried to solve this by making an startGameSequence() function that uses async and await, but it isn't working. What am I doing wrong?
Here's what I've got so far:
import 'package:audioplayers/audio_cache.dart';
import 'dart:async';
class GameScreen extends StatefulWidget {
#override
_GameScreenState createState() => _GameScreenState();
}
class _GameScreenState extends State<GameScreen> {
void loadAudio() {
final player = AudioCache();
player.load('audio/ready-321-go-music.mp3');
}
void playAudio() {
final player = AudioCache();
player.play('audio/ready-321-go-music.mp3');
}
void startGameSequence() async {
await loadAudio();
playAudio();
// After audio finishes loading / starts playing, THEN I'd like the 4-second delayed timer to start. (Currently, it seems that the time starts too early because the audio takes a bit to load.)
Future.delayed(
const Duration(seconds: 4),
() => startTimer(),
);
}
Timer _timer;
double _timeRemaining = 7.00;
void startTimer() {
const tick = const Duration(milliseconds: 10);
_timer = new Timer.periodic(
tick,
(Timer timer) => setState(
() {
if (_timeRemaining < 0.01) {
timer.cancel();
} else {
_timeRemaining = _timeRemaining - 0.01;
}
},
),
);
}
#override
initState() {
super.initState();
startGameSequence();
}
Thank you in advance for any help!
InitState is not async, wherefore this not working correctly.
A one solution is, load the audioFile in initState() and execute startGameSequence() in didUpdateWidget() function without the Future.delayed() .
#override
initState() {
super.initState();
await loadAudio();
}
#override
void didUpdateWidget(GameScreen oldWidget) {
startGameSequence()
super.didUpdateWidget(oldWidget);
}
void startGameSequence() {
playAudio();
}
This function execute just when the first layout appears on the screen.