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(() {});
},
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.
Related Questions
- → should I choose reactjs+f7 or f7+vue.js?
- → Phonegap Android write to sd card
- → Local reference jquery script in nanohttpd (Android)
- → Click to navigate on mobile devices
- → How to allow api access to android or ios app only(laravel)?
- → Access the Camera and CameraRoll on Android using React Native?
- → React native change listening port
- → What is the default unit of style in React Native?
- → Google play market autocomplete icon
- → Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `ListView`
- → Using Laravel with Genymotion
- → react native using like web-based ajax function
- → react native pdf View