292

I'd like to execute a function after a certain delay after my Widget is built. What's the idiomatic way of doing this in Flutter?

What I'm trying to achieve: I'd like to start with a default FlutterLogo Widget and then change its style property after some duration.

Bradley Campbell
  • 9,298
  • 6
  • 37
  • 47

10 Answers10

482

You can use Future.delayed to run your code after some time. e.g.:

Future.delayed(const Duration(milliseconds: 500), () {

// Here you can write your code

  setState(() {
    // Here you can write your code for open new view
  });

});

In setState function, you can write a code which is related to app UI e.g. refresh screen data, change label text, etc.

Rahul Sharma
  • 12,515
  • 6
  • 21
  • 30
  • 1
    To avoid a warning check that your widget is still mounted before calling setState – Tom Dec 01 '20 at 13:21
128

Trigger actions after countdown

Timer(Duration(seconds: 3), () {
  print("Yeah, this line is printed after 3 seconds");
});

Repeat actions

Timer.periodic(Duration(seconds: 5), (timer) {
  print(DateTime.now());
});

Trigger timer immediately

Timer(Duration(seconds: 0), () {
  print("Yeah, this line is printed immediately");
});
Jai Khambhayta
  • 4,198
  • 2
  • 22
  • 29
  • 7
    This has the advantage over `Future.delayed` in that it can be canceled if stored in a variable! – gruvw Apr 19 '22 at 20:45
98

Just leaving here the snippet everyone is looking for:

Future.delayed(Duration(milliseconds: 100), () {
  // Do something
});
Armands L.
  • 1,885
  • 2
  • 14
  • 18
  • hey Armands, by any chance you know how to solve this? https://stackoverflow.com/questions/68324422/how-to-make-text-transition-by-animation-upon-button-press – VegetaSaiyan Jul 10 '21 at 06:30
97

Figured it out

class AnimatedFlutterLogo extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _AnimatedFlutterLogoState();
}

class _AnimatedFlutterLogoState extends State<AnimatedFlutterLogo> {
  Timer _timer;
  FlutterLogoStyle _logoStyle = FlutterLogoStyle.markOnly;

  _AnimatedFlutterLogoState() {
    _timer = new Timer(const Duration(milliseconds: 400), () {
      setState(() {
        _logoStyle = FlutterLogoStyle.horizontal;
      });
    });
  }

  @override
  void dispose() {
    super.dispose();
    _timer.cancel();
  }

  @override
  Widget build(BuildContext context) {
    return new FlutterLogo(
      size: 200.0,
      textColor: Palette.white,
      style: _logoStyle,
    );
  }
}
Bradley Campbell
  • 9,298
  • 6
  • 37
  • 47
  • 1
    where did you import `Timer` from? – Lucem Aug 01 '18 at 06:27
  • 4
    got it `import 'dart:async'` – Lucem Aug 01 '18 at 06:43
  • one modification would be to put `timer = ...` in the `initState` override. That way, you have access to `widget` which is set in the `State<>` constructor. – stevenspiel Apr 01 '19 at 20:29
  • 2
    I don't t think this should be accepted answer, cause it not just runs code after delay, but also repeats code. @Rahul Sharma solution just for delay is much better. – Andris Jun 01 '20 at 13:37
  • Rahul's answer doesn't cancel the timer, so surely if your widget goes away you have a leak? (Note: I am not a flutter developer, I used this once a couple years ago!) – Bradley Campbell Jun 01 '20 at 19:34
  • 1
    @BradleyCampbell Rahul's answer doesn't have a timer. It's a function which runs once after the delay. – Banana Jun 06 '20 at 16:55
  • Yes, both APIs run a block of code after a delay. But the accepted answer here actually cancels the execution of that block of code should the widget disappear. This was to prevent memory leaks, but it might not be necessary! I'd need a flutter developer to check if the timer/future still executes after a widget is disposed – Bradley Campbell Jun 07 '20 at 16:06
  • I don't think this should be the accepted answer since the code keeps repeating until the widget is disposed, the solution should execute the code after the delay only once. – Luis_RH Dec 01 '21 at 19:33
  • 1
    No, it doesn't. https://api.dart.dev/stable/2.14.4/dart-async/Timer-class.html – Bradley Campbell Dec 02 '21 at 15:33
33

(Adding response on old q as this is the top result on google)

I tried yielding a new state in the callback within a bloc, and it didn't work. Tried with Timer and Future.delayed.

However, what did work was...

await Future.delayed(const Duration(milliseconds: 500));

yield newState;

Awaiting an empty future then running the function afterwards.

Ovidius Mazuru
  • 750
  • 7
  • 14
27

Synchronously

Future.delayed(Duration(milliseconds: 1000), () {
    // Your code
});

Asynchronously

await Future.delayed(const Duration(milliseconds: 1000));
Michael
  • 9,639
  • 3
  • 64
  • 69
Mohad Hadi
  • 1,826
  • 3
  • 24
  • 39
14

Future.delayed(Duration(seconds: 3) , your_function)

S.R Keshav
  • 1,965
  • 1
  • 11
  • 14
12

Just adding more description over the above answers

The Timer functionality works with below duration time also:

const Duration(
      {int days = 0,
      int hours = 0,
      int minutes = 0,
      int seconds = 0,
      int milliseconds = 0,
      int microseconds = 0})

Example:

  Timer(Duration(seconds: 3), () {
    print("print after every 3 seconds");
  });
Jitesh Mohite
  • 31,138
  • 12
  • 157
  • 147
  • hey Jitesh, by any chance you know how to solve this? https://stackoverflow.com/questions/68324422/how-to-make-text-transition-by-animation-upon-button-press – VegetaSaiyan Jul 10 '21 at 06:30
8

A quick way is using Future.delayed as below:

Future.delayed(Duration(seconds: 10), (){
    print("Wait for 10 seconds");
});

or you can change duration to milliseconds like this:

Future.delayed(Duration(milliseconds: 3000), () {
        print("Wait for 3000 milliseconds");
});
Fakhriddin Abdullaev
  • 4,169
  • 2
  • 35
  • 37
4
import 'dart:async';   
Timer timer;

void autoPress(){
  timer = new Timer(const Duration(seconds:2),(){
    print("This line will print after two seconds");
 });
}

autoPress();