Flutter - Using Timer and .cancel() function - flutter

*** UPDATE ***
I have a problem. When I use a Timer in Flutter and cancel() it afterwards, but as soon the cancel method is triggered, nothing happens.
var counter = 0;
Timer.periodic(const Duration(milliseconds: 50), (timer) {
developer.log('Actual counter ' + counter.toString());
counter++;
if (counter == 5) {
developer.log('TIMER DONE');
timer.cancel();
}
});
developer.log('This comes afterwards');
Expected out put:
Actual counter 0
Actual counter 1
Actual counter 2
Actual counter 3
Actual counter 4
TIMER DONE
This comes afterwards
The Output:
Actual counter 0
Actual counter 1
Actual counter 2
Actual counter 3
Actual counter 4
TIMER DONE
normally I should see a message 'this is afterwards' in the console, but it seems that with the cancel the complete method will be canceled.
Many thanks in advance.

Update: perform operation end of timer.
You need to add logic inside if condition to perform operation.
if (counter == firmwareList.length) {
timer.cancel();
developer.log('This comes afterwards'); //here
}
});
Here is an widget example
class TimerF extends StatefulWidget {
const TimerF({super.key});
#override
State<TimerF> createState() => _TimerFState();
}
class _TimerFState extends State<TimerF> {
var counter = 0;
Timer? timer;
bool isTimerActive = true;
#override
void initState() {
super.initState();
timer = Timer.periodic(const Duration(seconds: 1), (timer) {
print('Still timer');
if (counter == 5) {
timer.cancel();
isTimerActive = false;
}
counter++;
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Text("current value ${counter}"),
if (timer?.isActive == false) Text("Timer isnt active"),
if (isTimerActive == false) Text("Timer isnt active $isTimerActive"),
],
),
);
}
}
I can't see any increment on counter on current snippet. that's why counter remains 0 and doesnt meet the condition to cancel the timer.
Perhaps it will be
var counter = 0;
Timer.periodic(const Duration(milliseconds: 50), (timer) {
print('Still timer');
if (counter == 5) {
timer.cancel();
}
counter++; //increment the value
print('this is afterwards');
});

Here is a fully working example using a Timer
Timer? timer;
startTimer() {
var counter = 0;
timer = Timer.periodic(const Duration(milliseconds: 50), (timer) {
counter += 1;
print('Actual step $counter');
if(counter==5) {
cancelTimer();
}
});
}
cancelTimer() {
timer?.cancel();
print('this is afterwards');
//do something here
}
When you startTimer(), here is the output
Actual step 1
Actual step 2
Actual step 3
Actual step 4
Actual step 5
this is afterwards

Related

Flutter How can I use setState and only change one area and leave the other as it is?

I want a page that has a timer and also displays math problems. and whenever the correct answer has been entered, a new task should appear. But the problem is that whenever a new task appears, the timer is reset. How can I prevent this ?
late Timer timer;
double value = 45;
void startTimer() {
timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (value > 0) {
setState(() {
value--;
});
} else {
setState(() {
timer.cancel();
});
}
});
}
#override
void initState() {
// TODO: implement initState
super.initState();
startTimer();
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
void userTextFieldInput() {
controller.addListener(
() {
String rightResult = (firstIntValue + secondIntValue).toString();
String userResult = controller.text;
if (rightResult == userResult) {
setState(() {
DatabaseHelper(
firstUserValue: firstIntValue,
secondUserValue: secondIntValue,
finalUserResult: int.parse(controller.text),
).setDB();
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const CalculatePage(),
),
);
});
} else if (controller.text.length >= 2) {
controller.clear();
}
},
);
}
You should create two different state, one for timer and another one for the problems.
You can use the package flutter bloc to manage these state easily.

How to define a function in a text widget?

void valuerandomer() {
Future.delayed(Duration(milliseconds: 500), () {
int count = 0;
int max = 1000;
int min = 1;
Random rnd = new Random();
while (count != -1) {
count++;
value += rnd.nextInt(6) + (-5);
}
if (value > (max - 1)) {
value = 999;
} else if (value < 0) {
value = 0;
}
print(value);
});
}
I want the function to print every 500 miliseconds in the text widget so the value parameter starts with the value of 75 and changes every 500 milliseconds with this function.
How do I do that?
How do I declare this function in the text widget like Text('$valuerandomer')? cuz its just dont work. I tried just to type there $value but still doesnt work
For every x time, try using Timer.periodic
Timer? _timer;
String text = "initText";
#override
void dispose() {
_timer?.cancel();
super.dispose();
}
void valuerandomer() {
_timer = Timer.periodic(
Duration(milliseconds: 500),
(t) {
//perform your work
text = "newText ";
setState(() {});
},
);
}
Use funtion
Timer.periodic(Duration(/..),(timer){
//Put your logic
setState((){});
})

setState() or markNeedsBuild() called during build. Trying to make a simple timer in flutter

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

Flutter How to make it vibrate on the last count?

I made a counter application, the user can determine the number of their own count. if the count reaches the count limit, I want it vibrate at the last count. For example, if I specify the number 5, the smartphone will vibrate on the 5th tap. However, I have a problem, because the vibration appears on the 6th tap.
How to make it vibrate on the 5th beat?
here is my code:
int _counter = 0;
int _five = 5;
onTap: () async {
setState(() {
if (_counter != _five) {
_counter++;
} else if (_counter == _five) {
Vibration.vibrate(duration: 500);
_counter = _counter + 0;
} else {}
});
},
Your code need a little change like:
onTap: () async {
setState(() {
if (_counter < _five) {
_counter++;
}
if (_counter == _five) {
Vibration.vibrate(duration: 500);
} else {}
});
}

Stuck at fetching a new question after a timeout (using Flutter)

I am building a Flutter Quiz app where the user gets a specific duration of time to answer the question. If the user fails to answer within the given time frame, the next question is retrieved.
The starttimer method acts as a counter and stops at 1.
void starttimer() {
_counter = 10;
if (_timer != null) {
_timer.cancel();
}
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
if (_counter > 0) {
print(_counter);
_counter--;
} else {
_timer.cancel();
}
if (_counter == 1) {
// TODO: nextQuestion();
}
});
});
}
The questions are in a list and a index is used to obtain a specific question within the Text widget ex: Text(questionlist[i]).
The nextQuestion() needs to increment the index by 1.
How can I achieve this? Or is there any other way to retrieve the next question?
Try this logic:
void startTimer() {
_counter = 10;
_timer?.cancel();
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
if (_counter == 0) {
nextQuestion();
timer.cancel();
}
_counter--;
});
});
}