Stopping a function in flutter - flutter

I am new to flutter and I have a problem with a flutter function. It adds data to graph and I programmed a button to start updating the graph. How do I stop it? I created another button and I want to program it to stop the function that adds the graph.
The function:
void updateDataSource(Timer timer) {
chartData.add(LiveData(time++, (y)));
chartData.removeAt(0);
_chartSeriesController.updateDataSource(
addedDataIndex: chartData.length - 1, removedDataIndex: 0);
}
The first button:
onPressed: () {
Timer.periodic(const Duration(seconds: 1), updateDataSource);
},
The second button:
onPressed: () {
chartData.clear();
},
I put chartData.clear() but that clears everything and I am unable to call back the function again.
Thanks in advance!

This is due to your Timer.periodic function which is running every second
Solution:
Create a state timer variable
Timer? _timer;
Assign a value to the timer when you first onPressed
onPressed: (){
_timer = Timer.periodic(const Duration(seconds: 1), updateDataSource);
setState((){});
},
And when you want to stop adding graphs Do.
onPressed: () {
if(_timer !=null) {
_timer.cancel();
}
},

Related

How to cancel sub Timer inside nested Timer?

I am having a problem with cancelling one nested Timer. These are the code example I have:
import 'dart:async';
void main() async{
final timer =
Timer(const Duration(seconds: 1), () {
print('Timer 1');
Timer(const Duration(seconds:1),(){
print('Timer 2');
});
});
Timer(Duration(milliseconds: 1500),(){
timer.cancel();
print('timer cancelled');
});
}
The result:
Timer 1
timer cancelled
Timer 2
What I am expected:
Timer 1
timer cancelled
A little about my usecase, I want to create a quite complex animation and I use the nested Timer to set the specific timing of the animation.
The problem occur when the user move forward and instantinously move backward, the animation that still inside the Timer will still run 'forward' (because it's still deep inside the nested timer) even though the 'reverse' animation should be the only one that run.
That is why I am only expecting Timer 1 to be printed instead of both Timer 1 and 2 even though the Timer has been cancelled
Any feedback or input would be appreciated.
What I am expected:
Timer 1
timer cancelled
I think this will print your expected result. Just keep a reference to the second Timer. You can reuse the existing timer variable since after the first Timer fires to create the second Timer, you no longer need a reference to the first one.
import 'dart:async';
void main(List<String> args) {
Timer? timer = null;
timer = Timer(const Duration(seconds: 1), () {
print('Timer 1');
timer = Timer(const Duration(seconds: 1),(){
print('Timer 2');
});
});
Timer(Duration(milliseconds: 1500),(){
timer?.cancel();
print('timer cancelled');
});
}

How to wait seState to be finished and widgets to be built before calling another function?

Hi StackOverFlow community,
that's my first question here and I'm glad to be part of this community as it already helped me in plenty of things. I looked on this topic and didn't manage to find anything.
I would like to redirect the DefaultTabController to the new tab created after waiting that it's loaded and built.
I managed to find a workaround with the awaiting a Future.delayed wrapping setState but I don't think it's the best solution out there.
When not using this FutureDelayed I get an error due to the fact that the button function is trying to redirect to a tab not yet crated as the DefaultTabController has not been yet rebuilt.
Function for adding a new tab inside a bottomSheet
Future<int> _addNewTab() async {
await showModalBottomSheet(
...
...
IconButton(
onPressed: () {
final isValid =
_formKey.currentState!.validate();
if (!isValid) {
return;
}
Navigator.pop(context);
setState(() {
_tabs
.add(_newTab.text);
});
}
return _tabs.lenght-1;
Widget inside which I call the function
return DefaultTabController(
...
...
floatingActionButton: Padding(
//button to add a new tab
padding: const EdgeInsets.only(bottom: 25.0),
child: IconButton(
icon: Icon(
Icons.add_circle,
size: 55,
),
onPressed: () async {
var page = await _addNewTab();
//awaiting this future delayed because we can't show a page which is not built yet
await Future.delayed(const Duration(milliseconds: 10),
() {
setState(() {});
});
//moving to the new tab built after awaiting it
if (mounted) { //checking that context is still alive and usable
DefaultTabController.of(context)!.animateTo(page);
}
},
Thanks a lot for your help in advance :)
Thanks to Gwhyyy I discovered about SchedulerBinding.
Here a link with a similar question already answered with different solutions hoping it helps.
Flutter: Run method on Widget build complete
Have a good day!
yes, you have right, using the Future to wait for the 10 milliseconds fixes it but it's not the best solution.
instead :
first import the scheduler package, it's built-in in flutter, add this on top of your file :
import 'flutter/scheduler.dart';
then, replace this:
await Future.delayed(const Duration(milliseconds: 10),
() {
setState(() {});
});
with this:
SchedulerBinding.instance.addPostFrameCallback(
(_){
setState(() {});
})
this will schedule the SetState(() {}) just one frame after it finishes executing all the code in that onPressed function, so the result will be an immediate SetState(() {}) after your page is on.

How to display time on buttons in Flutter

Requirement:
I have 2 buttons, I want when I click on button 1 its text should be replaced by the current time, and the same for button 2.
Problem:
The problem is when I click on button 1 its text change to the current time, but when I click on button 2 after a few minutes its text changes to the same time that button 1 has.
Here is my code:
void initState() {
// TODO: implement initState
super.initState();
_getTime();
}
void _getTime() {
final String formattedDateTime =
DateFormat('kk:mm:ss').format(DateTime.now()).toString();
setState(() {
getTime = formattedDateTime;
print(getTime[0]);
});
}
var timeInText="Time in";
var timeOutText="Time out";
\\button 1
RoundedButton(icon: Icon(Icons.timer,color: Colors.white),
text:timeInText,
bgcolor: Colors.blue[500],
press:(){
setState(() {
timeInText=getTime;
});
})
//button 2
RoundedButton(icon: Icon(Icons.timer,color: Colors.white),
text:timeoutText,
bgcolor: Colors.blue[500],
press:(){
setState(() {
timeoutText=getTime;
});
})
please help to fix it. thanks
You call _getTime() only in initState. Time is stored on initialization and never updated after that. Since it's never updated it's showing the same time constantly.
To fix that add a _getTime() call to both of your onPressed functions like this:
onPressed: () {
_getTime();
setState(() {
timeoutText = getTime;
});
}),
You get the time one, when the button clicked. You have to write your method codes in setState too i think. And get the current time 🤔 i hope it will help

The periodic timer is duplicated in initState ()

When switching to another page, a periodic timer is started in initState (). But it is duplicated.
Or I am making a wrong transition to another page. Or initState () is doubled.
Code for moving from one page to another:
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new MapPage(phone: _phone)));
Timer call:
#override
void initState() {
super.initState();
_timerSendPointStart = Timer.periodic(Duration(seconds: 10), (timer) {
setState(() {
makePoint();
});
});
}
Can you please tell me where the error is and how to fix it?
use onWillPop() life cycle hook to stop the timer/delete the timer before navigating to another screen. otherwise, you will get the timer's overflow.
It's also good to cancel the timer in the dispose() function.

Flutter: How to stop timer after N seconds interval?

I am using below code to start the timer
Timer Snippet:
_increamentCounter() {
Timer.periodic(Duration(seconds: 2), (timer) {
setState(() {
_counter++;
});
});
}
RaisedButton raisedButton =
new RaisedButton(child: new Text("Button"), onPressed: () {
_increamentCounter();
});
What I all want is to stop this timer after specific(N) timer interval.
Since you want to cancel the Timer after a specific number of intervals and not after a specific time, perhaps this solution is more appropriate than the other answers?
Timer _incrementCounterTimer;
_incrementCounter() {
_incrementCounterTimer = Timer.periodic(Duration(seconds: 2), (timer) {
counter++;
if( counter == 5 ) // <-- Change this to your preferred value of N
_incrementCounterTimer.cancel();
setState(() {});
});
}
RaisedButton raisedButton = new RaisedButton(
child: new Text("Button"),
onPressed: () { _incrementCounter(); }
);
You can use a Future.delayed.
Future.delayed(const Duration(seconds: n), () => _increamentCounter());
Alternatively to Future.delayed(), you can also use
Timer(const Duration(seconds: n), () => _increamentCounter());
The Timer class exposes a couple extra methods like .cancel(), .tick, and isActive, so prefer it if you see yourself needing them down the road.