19

I am trying to build a countdown app for special days for example 11 d 2 h 30 m 23s to the new year but I can't reload my state every second so it just shows me the second that I loaded the page I don't know how to dynamically reload the page.

 import 'package:flutter/material.dart';

    class RopSayac extends StatefulWidget {
      _RopSayacState createState() => _RopSayacState();
    }

    class _RopSayacState extends State<RopSayac> {

      var now = DateTime.now().second.toString();
      String asd(){
        setState(() {
        now = DateTime.now().second.toString();

        });
        return now;
      }

      @override
      Widget build(BuildContext context) {


        return Container(
          child: new Text(asd()),
        );
      }
    }

This is what I got and it doesn't reload time. I am pretty new on the flutter.

Miguel Ruivo
  • 16,035
  • 7
  • 57
  • 87
isa türk
  • 707
  • 1
  • 10
  • 20

4 Answers4

39

As pskink and Günter mentioned, use a Timer. You can even use the periodic constructor that would fit well your scenario.

Note you don't need the asd() function. When you call setState(), the build method will be called automatically passing the new now property value.

If you want, use initState to set an initial value and, as in this example, setup the Timer.

import 'dart:async';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(title: 'Timer Periodic Demo', home: RopSayac());
  }
}

class RopSayac extends StatefulWidget {
  _RopSayacState createState() => _RopSayacState();
}

class _RopSayacState extends State<RopSayac> {
  String _now;
  Timer _everySecond;

  @override
  void initState() {
    super.initState();

    // sets first value
    _now = DateTime.now().second.toString();

    // defines a timer 
    _everySecond = Timer.periodic(Duration(seconds: 1), (Timer t) {
      setState(() {
        _now = DateTime.now().second.toString();
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: new Text(_now),
      ),
    );
  }
}
Feu
  • 5,372
  • 1
  • 31
  • 57
  • 1
    Thank you so much. Now ı understand init state logic better. Flutter feels like weird after java and .net – isa türk Dec 16 '18 at 12:01
  • Can you also explain what does dipose() do – isa türk Dec 16 '18 at 12:13
  • 3
    `dispose` is called when the widget is no longer needed and it's about to be destroyed. Let's say you open a connection in `initState` and for some reason you keep it open, you would implement the `dispose` method as it would be a good time to close that connection. That's kind of a bad example, but gives you the idea. [Check also this](https://docs.flutter.io/flutter/widgets/State/dispose.html). – Feu Dec 16 '18 at 18:12
6

This recursive method should be enough for what you want. The seconds set as 1 will keep triggering setState each second, thus refreshing your widget tree.

void _timer() {
    Future.delayed(Duration(seconds: 1)).then((_) {
      setState(() {
        print("1 second closer to NYE!");
        // Anything else you want
      });
      _timer();
    });
  }
Miguel Ruivo
  • 16,035
  • 7
  • 57
  • 87
5

There's this excellent library called timer_builder. I think it'll help you out.

Example from the pub page:

import 'package:timer_builder/timer_builder.dart';

class ClockWidget extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return TimerBuilder.periodic(Duration(seconds: 1), //updates every second
      builder: (context) {
        return Text("${DateTime.now()}");
      }
    );
  }

}
-2

Here's what I do. In my case I'm polling a webservice in _liveUpdate()

void startUpdates(AppState appState) async {
await new Future.delayed(const Duration(milliseconds: 100));
while (true) {
  _liveUpdate();
  appState.setState(() {});

  await new Future.delayed(const Duration(seconds : 15));
}
dakamojo
  • 1,839
  • 5
  • 21
  • 35