How to manage two ListView with data in firestore in the same screen in Flutter

572

In order to read both info from the same Stream you need to expose it as a broadcast stream first:

final streamQuery = _firestore
          .collection('books')
          .snapshots()
          .asBroadcastStream();
return StreamBuilder<QuerySnapshot>(
      stream: streamQuery,
      builder: ...
Share:
572
M4trix Dev
Author by

M4trix Dev

Updated on December 14, 2022

Comments

  • M4trix Dev
    M4trix Dev over 1 year

    I am building a Flutter app and I have a screen with 2 ListViews. The data source is a firestore database and it is the same for both list however one list presents only an image while the other list presents the image PLUS other information.

    I have managed to found a solution to display both List however it does not seem the most effective because I believe I am downloading the same data 2 time. Do you have any suggestion on how to make it better???

    See my code below

    final _firestore = Firestore.instance;
    
    class ItemPage extends StatefulWidget {
      @override
      _ItemPageState createState() => _ItemPageState();
    }
    
    class _ItemPageState extends State<ItemPage> {
      bool showSpinner = false;
    
      @override
      Widget build(BuildContext context) {
        return CupertinoPageScaffold(
          navigationBar: CupertinoNavigationBar(
            heroTag: 'itemppage',
            transitionBetweenRoutes: false,
            middle: Text(
              appData.categoryName,
              style: kSendButtonTextStyle,
            ),
          ),
          child: Scaffold(
            backgroundColor: kColorPrimary,
            body: ModalProgressHUD(
              inAsyncCall: showSpinner,
              child: Column(
                children: <Widget>[
                  Expanded(
                    child: ItemList(),
                  ),
                  Container(
                    height: 80.0,
                    child: ItemListBottomScroll(),
                  )
                ],
              ),
            ),
          ),
        );
      }
    }
    
    class ItemList extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return StreamBuilder<QuerySnapshot>(
          stream: _firestore
              .collection('books')
              .snapshots(),
          builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
            if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
            switch (snapshot.connectionState) {
              case ConnectionState.waiting:
                return new Text(
                  'Loading...',
                  style: kSendButtonTextStyle,
                );
              default:
                return new PageView(
                  scrollDirection: Axis.horizontal,
                  children:
                      snapshot.data.documents.map((DocumentSnapshot document) {
                    return SingleChildScrollView(
                      child: Column(
                        children: <Widget>[
                          Container(
                            margin: EdgeInsets.all(10.0),
                            child: Stack(
                              children: <Widget>[
                                CachedNetworkImage(
                                    imageUrl: document['url'],
                                    placeholder: (context, url) =>
                                        new CircularProgressIndicator(),
                                    errorWidget: (context, url, error) =>
                                        new Icon(Icons.error),
                                    width: MediaQuery.of(context).size.width - 20,
                                    height:
                                        (MediaQuery.of(context).size.width - 20),
                                    fit: BoxFit.cover),
                                Positioned(
                                  bottom: 0.0,
                                  right: 0.0,
                                  child: IconButton(
                                    color: kColorAccent.withOpacity(0.8),
                                    iconSize: 50.0,
                                    icon: Icon(Icons.add_circle),
                                    onPressed: () {
                                      print(document['name'] +
                                          document.documentID +
                                          ' clicked');
                                    },
                                  ),
                                ),
                              ],
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.only(
                                left: 10.0, right: 10.0, bottom: 10.0),
                            child: Row(
                              children: <Widget>[
                                Expanded(
                                  child: Text(
                                    document['name'],
                                    style: kSendButtonTextStyle,
                                  ),
                                  flex: 3,
                                ),
                                Expanded(
                                  child: Text(
                                    appData.currency + document['price'],
                                    textAlign: TextAlign.right,
                                    style: kDescriptionTextStyle,
                                  ),
                                  flex: 1,
                                ),
                              ],
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.only(left: 10.0, right: 10.0),
                            child: Container(
                              child: Text(
                                document['description'],
                                style: kDescriptionTextStyle,
                              ),
                              width: double.infinity,
                            ),
                          )
                        ],
                      ),
                    );
                  }).toList(),
                );
            }
          },
        );
      }
    }
    
    class ItemListBottomScroll extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return StreamBuilder<QuerySnapshot>(
          stream: _firestore
              .collection('books')
              .snapshots(),
          builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
            if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
            switch (snapshot.connectionState) {
              case ConnectionState.waiting:
                return new Text('Loading...');
              default:
                return new ListView(
                  scrollDirection: Axis.horizontal,
                  children:
                      snapshot.data.documents.map((DocumentSnapshot document) {
                    return Stack(
                      children: <Widget>[
                        Container(
                          height: 80.0,
                          width: 90.0,
                          padding: EdgeInsets.only(left: 10.0),
                          child: GestureDetector(
                            onTap: () {
                              print(document['name'] +
                                  document.documentID +
                                  ' bottom clicked');
                            },
                            child: new CachedNetworkImage(
                                imageUrl: document['url'],
                                placeholder: (context, url) =>
                                    new CircularProgressIndicator(),
                                errorWidget: (context, url, error) =>
                                    new Icon(Icons.error),
                                fit: BoxFit.cover),
                          ),
                        ),
                      ],
                    );
                  }).toList(),
                );
            }
          },
        );
      }
    }