5

I want to reload my list when Navigator.pop, but i can't do that.

My code:

class ConfigCNPJPage extends StatefulWidget {
  bool voltarTela;
  ConfigCNPJPage({Key key, this.voltarTela}) : super(key: key);

  @override
  ConfigCNPJPageState createState() => new ConfigCNPJPageState();
}

class ConfigCNPJPageState extends State<ConfigCNPJPage>
    with SingleTickerProviderStateMixin {
    ResultConfig BD;
    List<Map> list;
    List<Widget> listArray = [];

    Stream myStream;


  Future setupList() async {
    ConfigDatabase db = ConfigDatabase();
    var banco = await db.initDB();
    list = await banco.rawQuery('SELECT * FROM Empresa');
    return list;
  }



    @override
    void initState() {
      super.initState();
      myStream = setupList()?.asStream();
    }



  @override
  Widget build(BuildContext context) {
    return new StreamBuilder(
      stream: myStream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return snapshot.hasData?  new Scaffold(
          resizeToAvoidBottomPadding: false,
            appBar: new AppBar(
              title: new Text('Configurar Empresa'),
              actions: <Widget>[
                new IconButton(icon: const Icon(Icons.add), onPressed: () {
                  Navigator.pushNamed(context, "NovoCNPJ").then((value) {
                      setState(() {
                        myStream = setupList()?.asStream();
                      });
                  });
                })
              ],
            ),
            body: new Column(
              children: <Widget>[
                  criarLista()
              ],
            ),
        ):new Center(child: new RefreshProgressIndicator());
      },);
  }
}

I want to reaload this Stream after the pop, with the setState, but isn't working. Anyone can help?

I needs to rebuild that StreamBuilder? or reload just the list?

With the StreamBuilder, i need to do the setState and if i got the streamBuilder rebuilded it will work?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Rafael Nonino
  • 180
  • 4
  • 15

1 Answers1

0

I guess you would have to use a StreamController instead of a Stream in that example.

From your example, see _streamController occurrences.

class ConfigCNPJPage extends StatefulWidget {
  bool voltarTela;
  ConfigCNPJPage({Key key, this.voltarTela}) : super(key: key);

  @override
  ConfigCNPJPageState createState() => new ConfigCNPJPageState();
}

class ConfigCNPJPageState extends State<ConfigCNPJPage>
    with SingleTickerProviderStateMixin {
    ResultConfig BD;
    List<Map> list;
    List<Widget> listArray = [];

    StreamController _streamController;


  Future setupList() async {
    ConfigDatabase db = ConfigDatabase();
    var banco = await db.initDB();
    list = await banco.rawQuery('SELECT * FROM Empresa');
    return list;
  }



    @override
    void initState() {
      super.initState();
      _streamController = new StreamController();
      setupList()?.then((o) => _streamController.add(o));
    }



  @override
  Widget build(BuildContext context) {
    return new StreamBuilder(
      stream: _streamController.stream,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        return snapshot.hasData?  new Scaffold(
          resizeToAvoidBottomPadding: false,
            appBar: new AppBar(
              title: new Text('Configurar Empresa'),
              actions: <Widget>[
                new IconButton(icon: const Icon(Icons.add), onPressed: () {
                  Navigator.pushNamed(context, "NovoCNPJ").then((value) {
                      setState(() {
                        _streamController.add(value);
                      });
                  });
                })
              ],
            ),
            body: new Column(
              children: <Widget>[
                  criarLista()
              ],
            ),
        ):new Center(child: new RefreshProgressIndicator());
      },);
  }
}

But in your use case, do you have only ONE empresa/company or will you have many?

If you have only one, instead of having a Stream, it would be way easier to manage just one single _empresa / _company object..

If you expect to have a list of objects, then I wouldn't use a StreamBuilder as well. I would manage a List<Empresa> _empresas as well.

class ConfigCNPJPage extends StatefulWidget {
  bool voltarTela;
  ConfigCNPJPage({Key key, this.voltarTela}) : super(key: key);

  @override
  ConfigCNPJPageState createState() => new ConfigCNPJPageState();
}

class ConfigCNPJPageState extends State<ConfigCNPJPage>
    with SingleTickerProviderStateMixin {
    ResultConfig BD;
    List<Map> list;
    List<Widget> listArray = [];

    List<Empresa> _empresas;


  Future setupList() async {
    ConfigDatabase db = ConfigDatabase();
    var banco = await db.initDB();
    list = await banco.rawQuery('SELECT * FROM Empresa');
    return list;
  }

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

    setupList()?.then((o) {
      if (_empresas == null) _empresas = new List();

      // if o is a list, perform a forEach on it

      _empresas.add(new Empresa(o))
    });
  }

  @override
  Widget build(BuildContext context) {
    // o melhor seria usar outra variavel pra controlar o loading,
    //   mas deve funcionar assim
    return _empresas == null
      ? new Center(child: new RefreshProgressIndicator())
      : new Scaffold(
          resizeToAvoidBottomPadding: false,
            appBar: new AppBar(
              title: new Text('Configurar Empresa'),
              actions: <Widget>[
                new IconButton(icon: const Icon(Icons.add), onPressed: () {
                  Navigator.pushNamed(context, "NovoCNPJ").then((value) {
                      setState(() {
                        _empresas.add(new Empresa(value));
                      });
                  });
                })
              ],
            ),
            body: new Column(
              children: <Widget>[
                  criarLista()
              ],
            ),
        );
  }
}

Good luck!

Feu
  • 5,372
  • 1
  • 31
  • 57
  • Hey @Feu, i get the follow error: flutter: Class 'Future' has no instance method 'listen'. flutter: Receiver: Instance of 'Future'. The method setupList, as future, don't have the listen – Rafael Nonino Aug 07 '18 at 14:33
  • Now I see your setupList() returns a `Future`. You can use `.then()` - updated the answer. But again I would avoid that approach and would stick to the simpler second method. – Feu Aug 07 '18 at 14:50
  • Hey @Feu, i tried again, don't get errors, but the list still the same and me screen don't update, i need to pop and reopen to appears the new item, i think the setState don't are reloading the list or doing setupList() – Rafael Nonino Aug 07 '18 at 14:58
  • are you sure the setState() from the Navigator.pushNamed is being called? if you want that after the Navigator.push the list gets reloaded, you should be running setupList() in there instead of _empresas.add()... – Feu Aug 07 '18 at 15:01
  • i put a print('test'); and printed inside setState but the setupList isn't :c – Rafael Nonino Aug 07 '18 at 16:55
  • and are you calling setupList again in the setState inside the Navigator callback? – Feu Aug 07 '18 at 23:10
  • Ya, but i think that setupList aren't working inside the setState, Streambuilders loads just 1 time? – Rafael Nonino Aug 08 '18 at 11:17
  • StreamBuilders render every time a new event is yielded in the stream. (in that example, when _refreshController.add() is called). – Feu Aug 08 '18 at 20:34