问题
I tried two posibilities but the firebase data isnt being stored in the products list.The app page returns no data as there is nothing in procucts list. foollowing list returns data succesfully.The second possibilty that i tried and the Consolelog is in this pastebin link below: https://pastebin.com/DM47YHY6
List<String> foollowingList = [];
List<NetworkImage> _listOfImages = <NetworkImage>[];
List<DocumentSnapshot> products = []; // stores fetched products
bool isLoading = true; // track if products fetching
bool hasMore = true; // flag for more products available or not
int documentLimit = 10; // documents to be fetched per request
DocumentSnapshot lastDocument; // flag for last document from where next 10 records to be fetched
ScrollController _scrollController = ScrollController(); /
void initState() {
super.initState();
getFfollowing();
getPosts();
_scrollController.addListener(() {
double maxScroll = _scrollController.position.maxScrollExtent;
double currentScroll = _scrollController.position.pixels;
double delta = MediaQuery.of(context).size.height * 0.20;
if (maxScroll - currentScroll <= delta) {
getMorePosts();
}
});
}
getFfollowing() async {
QuerySnapshot snapshot = await followingRef
.document(currentUser.id)
.collection('userFollowing')
.getDocuments();
setState(() {
foollowingList = snapshot.documents.map((doc) => doc.documentID).toList();
});
}
getPosts()async{
for( int i=0; i< foollowingList.length; i++) {
Query q = Firestore.instance
.collection('posts/${foollowingList[i]}/userPosts')
.orderBy('ownerId')
.orderBy('timestamp', descending: true)
.limit(documentLimit);
setState(() {
isLoading = true;
});
QuerySnapshot querySnapshot = await q.getDocuments();
print("kjndskjl$products");
lastDocument = querySnapshot.documents[querySnapshot.documents.length - 1];
products = querySnapshot.documents;
setState(() {
isLoading = false;
});
}
}
getMorePosts()async{
print('get more called');
if(hasMore == false){
return;
} if(hasMore == true){
return;
}
hasMore = true;
for( int i=0; i< foollowingList.length; i++) {
Query q = await Firestore.instance
.collection('posts/${foollowingList[i]}/userPosts')
.orderBy('ownerId')
.orderBy('timestamp', descending: true)
.startAfterDocument(lastDocument)
.limit(documentLimit);
QuerySnapshot querySnapshot = await q.getDocuments();
if (querySnapshot.documents.length == 0) {
hasMore = false;
}
lastDocument = querySnapshot.documents[querySnapshot.documents.length - 1];
products.addAll(querySnapshot.documents);
setState(() {
hasMore = false;
print(products);
});
}
}
buildPosts(){
return
Column(children: [
Expanded(
child: products.length == 0
? Center(
child: Text('No Data...'),
)
: ListView.builder(
controller: _scrollController,
itemCount: products.length,
itemBuilder: (context, index) {
return
FutureBuilder(
future: usersRef.document(products[index].data['ownerId']).get(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return circularProgress();
}
User user = User.fromDocument(snapshot.data);
return Column(children: <Widget>[
ListTile(
leading: GestureDetector(
onTap: () => showProfile(context, profileId: user.id),
child: CircleAvatar(
backgroundImage: CachedNetworkImageProvider(user.photoUrl),
backgroundColor: Colors.grey,
),
),
title: GestureDetector(
onTap: () => showProfile(context, profileId: user.id),
child: Text(
user.displayName,
style: TextStyle(
color: kText,
fontWeight: FontWeight.bold,
),
),
),
subtitle: GestureDetector(
onTap: () => showProfile(context, profileId: user.id),
child: Text(user.username,
style: TextStyle(color: kIcon),),
),),
cachedNetworkImage(products[index].data['mediaUrl']),
Divider(color: kGrey,),
],
);
},
);
![
回答1:
In your first code
getMorePosts()async{
print('get more called');
if(hasMore == false){
return;
} if(hasMore == true){
return;
}
//The rest is dead code, you always return if hasMore is true or false
....
}
In your Snippet it seems it actually fills the prodcuts list but user is null (The getter 'id' was called on null), are you sure User user = User.fromDocument(snapshot.data); is parsing the data correctly? try changing showProfile(context, profileId: user?.id ?? 1) just to test it (I don't know if id should be an int, String, etc but in case of String change the 1 with some String 'Test')
UPDATE
Instead of running getPost in initState run it at the end of getFfollowing
void initState() {
super.initState();
getFfollowing();
//getPosts(); this could run after getFfollowing ends, where the list is empty
_scrollController.addListener(() {
double maxScroll = _scrollController.position.maxScrollExtent;
double currentScroll = _scrollController.position.pixels;
double delta = MediaQuery.of(context).size.height * 0.20;
if (maxScroll - currentScroll <= delta) {
getMorePosts();
}
});
}
getFfollowing() async {
QuerySnapshot snapshot = await followingRef
.document(currentUser.id)
.collection('userFollowing')
.getDocuments();
setState(() {
foollowingList = snapshot.documents.map((doc) => doc.documentID).toList();
});
if(foollowingList.isNotEmpty) await getPosts(); //run it here when you're sure the future is completed and the list is full
}
The trick is that initState cannot run a Future, so it will try to run getFfollowing and getPosts in the order they're called, but putting getPosts inside getFfollowing, which is async, assure you that it will run only when the other code ends. Also try to avoid using setState inside the for, this will make it rebuild a lot of times unnecesary, just put it at the beginning and end
getPosts()async{
setState(() => isLoading = true);
for( int i=0; i< foollowingList.length; i++) {
Query q = Firestore.instance
.collection('posts/${foollowingList[i]}/userPosts')
.orderBy('ownerId')
.orderBy('timestamp', descending: true)
.limit(documentLimit);
QuerySnapshot querySnapshot = await q.getDocuments();
print("kjndskjl$products");
lastDocument = querySnapshot.documents[querySnapshot.documents.length - 1];
products = querySnapshot.documents;
}
setState(() => isLoading = false);
}
来源:https://stackoverflow.com/questions/62924101/flutter-pagination-with-firebase-not-working-for-me