I have been using a FutureBuilder to read data from an api, and update the UI when it completes. All good, but now I want to refresh this every 5 minutes. I thought I could do this with a Timer. My code

class _MyTileState extends State<MyTile> {

  late Future<MyData?> myFuture = fetchMyData();

  Widget build(BuildContext context) {
    return Column(
      children: [
          future: myFuture, 
          builder: (BuildContext context, AsyncSnapshot<MyData?> snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator();
            } else if (snapshot.hasError) {
              return Text('Error: ${snapshot.error}');
            } else {
              return Text(snapshot.data.title);

  Future<MyData?> fetchMyData() async {
    var myData = await readMyData();
    return myData;

If I add a timer I get an error message : The instance member ‘fetchMyData’ can’t be accessed in an initializer

Timer timer = Timer(Duration(minutes: 5), () {
    myFuture = fetchMyData();
    setState(() {});

While trying to sort this, it has become apparent that FutureBuilder should not be used to refresh. Instead use a StreamBuilder. But this just displays the CircularProgressIndicator and only appears to run once

    stream: fetchMyDataStream(),
    builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.active) {
      return Text(snapshot.data.title);

    return CircularProgressIndicator();

  Stream<MyData> get fetchMyDataStream() async* {
    print("start fetch my data stream");
    await Future.delayed(Duration(seconds: 5)); // set to seconds for testing

    var myData = await readMyData();
    yield myData;

I am trying to work out which way I should be going – FutureBuilder or StreamBuilder? And for the preferred option, what I am doing wrong.


Khám phá các thẻ bài đăng