Andrew Stevenson
Andrew Stevenson

Reputation: 658

How do I update the time using Streams in Flutter?

I've been investigating the use of streams as I think this will the best solution for my app. I want to be able to check the time at specific intervals, then change the theme of a map automatically depending on whether the sun has risen or set. I have the themes and I have the sun code, but I need to join them together.

This is my code so far. If I use a double for the controller and subscription and simply generate a random number, then all is well. I get a different randomly generated number every second.

However, using the code below simply shows the same time over again.

Can somebody point me in the right direction with this?

import 'dart:async';
import 'dart:core';

import 'package:flutter/material.dart';

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

class StreamTest extends StatefulWidget {
  @override
  _StreamTestState createState() => _StreamTestState();
}

class _StreamTestState extends State<StreamTest> {
  StreamController<DateTime> controller =
      StreamController<DateTime>.broadcast();
  StreamSubscription<DateTime> streamSubscription;
  DateTime currentTime = DateTime.now();

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Stream Demo",
      home: Scaffold(
        body: Center(
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              MaterialButton(
                color: Colors.yellow,
                child: Text("Subscribe"),
                onPressed: () async {
                  getTime().listen((value) {
                    print('CURRENT TIME $currentTime');
                  });
                },
              ),
              MaterialButton(
                child: Text('Unsubscribe'),
                color: Colors.red[200],
                onPressed: () {
                  streamSubscription.cancel();
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Stream<DateTime> getTime() async* {
  DateTime currentTime = DateTime.now();
  while (true) {
    await Future.delayed(Duration(seconds: 1));
    yield currentTime;
  }
}

thanks

Upvotes: 3

Views: 13147

Answers (2)

p2hari
p2hari

Reputation: 558

as @pskink mentioned you can use Stream.periodic.

DateTime current = DateTime.now();
Stream timer = Stream.periodic( Duration(seconds: 1), (i){
       current = current.add(Duration(seconds: 1));
      return current;
    });

    timer.listen((data)=> print(data));

Upvotes: 6

Igor Kharakhordin
Igor Kharakhordin

Reputation: 9923

Inside your while (true) loop you're yielding the same variable you've set before. If you change it to yield DateTime.now() it will generate new values each iteration.

Also change variable inside print call to value: print('CURRENT TIME $value');.

To cancel the subscription later, store the value returned by listen method:

streamSubscription = getTime().listen((value) {

Result:

I/flutter ( 5716): CURRENT TIME 2019-11-14 13:50:34.318898
I/flutter ( 5716): CURRENT TIME 2019-11-14 13:50:35.323906
I/flutter ( 5716): CURRENT TIME 2019-11-14 13:50:36.328085
I/flutter ( 5716): CURRENT TIME 2019-11-14 13:50:37.332919

Upvotes: 2

Related Questions