Ganessa
Ganessa

Reputation: 882

Update the display on a regular basis in flutter

In flutter, we want to update the display on a regular basis. We can update the display when the value changes. However, the set value does not change in this case. Therefore, we do not know what to do as a trigger to update the display.

We changed from Stateless Widget to Stateful Widget. And we started the timer in initState() and canceled the timer in dispose(). We regularly call notifyListeners () on ScopedModel and are updating the drawing.

It works as expected. Unfortunately, it is not a beautiful way. It is hard to understand, it is annoying. Do not you know a better way? How should we do?

We will clarify our implementation example below. It is a minimal code.

xxxxx_widget.dart

import 'package:flutter/material.dart';
import 'package:pregnancy/scoped_model/xxxxx_model.dart';
import 'package:pregnancy/widgets/yyyyy_widget.dart';
import 'package:scoped_model/scoped_model.dart';

class XxxxxWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ScopedModel<XxxxxModel>(
      model: XxxxxModel(),
      child: YyyyyWidget(),
    );
  }
}

yyyyy_widget.dart

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:pregnancy/scoped_model/xxxxx_model.dart';
import 'package:scoped_model/scoped_model.dart';

class YyyyyWidget extends StatefulWidget {
  @override
  YyyyyWidgetState createState() {
    return new YyyyyWidgetState();
  }
}

class YyyyyWidgetState extends State<YyyyyWidget> {
  Timer _timer;

  @override
  void initState() {
    _timer = Timer.periodic(
      const Duration(milliseconds: 500),
      (Timer t) {
        XxxxxModel.of(context).notify();
      },
    );
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    return ScopedModelDescendant<XxxxxModel>(
      builder: (context, child, model) {
        var diff = model.datetime.difference(DateTime.now());
        var hours = diff.inHours.remainder(Duration.hoursPerDay);
        var minutes = diff.inMinutes.remainder(Duration.minutesPerHour);
        var seconds = diff.inSeconds.remainder(Duration.secondsPerMinute);
        return Text('${hours} hours ${minutes} minutes ${seconds} seconds');
      },
    );
  }
}

xxxxx_model.dart

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

class XxxxxModel extends Model {
  static XxxxxModel of(BuildContext context) =>
      ScopedModel.of<XxxxxModel>(context);

  DateTime _datetime = DateTime.now().add(Duration(days: 1));

  get datetime => _datetime;

  set datetime(DateTime value) {
    _datetime = value;
    notifyListeners();
  }

  void notify() {
    notifyListeners();
  }
}

Upvotes: 2

Views: 2038

Answers (1)

boformer
boformer

Reputation: 30103

You could use a StreamBuilder that listens to an interval stream. It automatically manages the subscription.

Your model can provide the stream as a property.

Upvotes: 1

Related Questions