Flutter pagination with firebase not working for me

こ雲淡風輕ζ 提交于 2020-08-10 18:53:09

问题


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,),
                  ],

                  );
                },
              );

enter image description here![


回答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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!