Ad

Flutter List Not Getting All Values

I had a FutureBuilder (great to have loading) getting my DocumentSnapshot list from Firebase but the problem was that it was rebuilding it over and over again if I push/pop a screen. To fix that I finally placed it on initState but I have one problem, I'm not getting all the documents from it sometimes.

I have a button to enable country filter and disable, each time I press it almost instantly show my documents and for example I have 11 total and 5 filtered but I don't get them all sometimes and until gets the values I get app error (length of _userList?). I tried to place a Future to force await but I'm not being able, please advise.

var _userList;

_fetchUserList() {
    Future<QuerySnapshot> snapshot;
    if (_countryFilter) {
      //print('COUNTRY FILTER');
      snapshot = Firestore.instance.collection('u').where('country', isEqualTo: country).getDocuments();
    } else {
      //print('ALL FILTER');
      snapshot = Firestore.instance.collection('u').getDocuments();
    }
    snapshot.then((QuerySnapshot result) {
      final List<DocumentSnapshot> documents = result.documents;
      if (documents.length > 0) {
        final List<DocumentSnapshot> availableUsers =
            documents.where((DocumentSnapshot documentSnapshot) => documentSnapshot['userId'] != _id).toList();
        //print('userList Size: ' + availableUsers.length.toString());

        List<DocumentSnapshot> userShuffle = _shuffle(availableUsers);
        setState(() {
          _userList = userShuffle;
        });
      }
    });
  }

This is my GridView:

GridView.builder(
                    padding: const EdgeInsets.all(10.0),
                    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                        crossAxisCount: 2, mainAxisSpacing: 10.0, crossAxisSpacing: 10.0, childAspectRatio: 0.85),
                    itemBuilder: (context, index) {
                      return _buildItem(context, _userList[index]);
                    },
                    itemCount: _userList.length,
                  )

Button:

onPressed: () async {
            if (_countryFilter) {
              _countryFilter = false;
            } else {
              _countryFilter = true;
            }
            await _fetchUserList();
            setState(() {});
          },
Ad

Answer

I've managed to make it work using some validations. Also the problem of the different user lenght was because of the "country" variable was used on the buildItem too.

Future _fetchUserList() async {
    setState(() {
      _userList = null;
      _userLenght = null;
    });
    QuerySnapshot snapshot;
    if (_countryFilter) {
      snapshot = await Firestore.instance.collection('u').where('country', isEqualTo: _myCountry).getDocuments();
    } else {
      snapshot = await Firestore.instance.collection('u').getDocuments();
    }

    final List<DocumentSnapshot> documents = snapshot.documents;
    if (documents.length > 0) {
      final List<DocumentSnapshot> availableUsers =
          documents.where((DocumentSnapshot documentSnapshot) => documentSnapshot['userId'] != _id).toList();
      _userLenght = availableUsers.length;

      if (_userLenght > 0) {
        List<DocumentSnapshot> userShuffle = _shuffle(availableUsers);
        _userList = userShuffle;
      }
      setState(() {});
    }
  }
(_userList == null && _userLenght == null)
                      ? Container(
                          child: Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            crossAxisAlignment: CrossAxisAlignment.stretch,
                            children: <Widget>[
                              Center(
                                child: Container(
                                  width: 50.0,
                                  height: 50.0,
                                  alignment: Alignment.center,
                                  child: CircularProgressIndicator(
                                    valueColor: AlwaysStoppedAnimation<Color>(Theme.of(context).primaryColor),
                                    strokeWidth: 2.0,
                                  ),
                                ),
                              ),
                              SizedBox(height: 12.0),
                              Text(
                                "We are loading the users",
                                style: TextStyle(
                                  color: Colors.black54,
                                  fontWeight: FontWeight.bold,
                                ),
                                textAlign: TextAlign.center,
                              ),
                            ],
                          ),
                        )
                      : (_userLenght == 0)
                          ? Container(
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.center,
                                crossAxisAlignment: CrossAxisAlignment.stretch,
                                children: <Widget>[
                                  Center(
                                    child: Icon(
                                      Icons.supervisor_account,
                                      color: Theme.of(context).primaryColor.withOpacity(0.8),
                                      size: 50.0,
                                    ),
                                  ),
                                  SizedBox(height: 12.0),
                                  Text(
                                    "No one was found\nTry reloading the screen",
                                    style: TextStyle(
                                      color: Colors.black54,
                                      fontWeight: FontWeight.bold,
                                    ),
                                    textAlign: TextAlign.center,
                                  ),
                                ],
                              ),
                            )
                          : GridView.builder(
                              padding: const EdgeInsets.all(10.0),
                              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                                  crossAxisCount: 2,
                                  mainAxisSpacing: 10.0,
                                  crossAxisSpacing: 10.0,
                                  childAspectRatio: 0.85),
                              itemBuilder: (context, index) {
                                return _buildItem(context, _userList[index]);
                              },
                              itemCount: _userLenght,
                            ),

Hope this helps someone. With this I was able to stop screen userlist shuffle each time I push and pop a screen since it's on the initState and Button only.

Ad
source: stackoverflow.com
Ad