Flutter - How to pass Firestore ID list to a Futurebuilder?

Asked

Viewed 529 times

4

I’m developing a book app and need help uploading the user’s favorite book list.

I don’t know the way I’m doing it would be the right one, I’m saving the Ids of all the books that the favorite user on a firestore list, then I retrieve that list from within the list favoritesId within the method getFavoritesId(), and now is where the problem occurs, within the method _makeFavoriteList(), how to recover only the data from books that have ids within this list and show them in Gridview?

coleção livros

coleção usuários

class FavoriteScreen extends StatefulWidget {

  @override
  _FavoriteScreenState createState() => _FavoriteScreenState();
}

class _FavoriteScreenState extends State<FavoriteScreen> {

  CollectionReference booksRef = Firestore.instance.collection("books");
  Future<QuerySnapshot> futureBooks;
  UserModel model = UserModel();
  FirebaseUser firebaseUser;
  FirebaseAuth _auth = FirebaseAuth.instance;
  List<String> favoritesId = [];


  @override
  void initState() {
    getFavoritesId();
    super.initState();
  }

  void getFavoritesId() async{

    List<String> favoritesId = [];

  firebaseUser = await _auth.currentUser();

  DocumentSnapshot querySnapshot = await Firestore.instance.collection("users")
      .document(firebaseUser.uid).get();

  if(querySnapshot.exists && querySnapshot.data.containsKey("favorites") &&
    querySnapshot.data["favorites"] is List && querySnapshot.data["favorites"].length != null){

    for(int i= 0; i < querySnapshot.data["favorites"].length; i++){
      favoritesId.add(querySnapshot.data["favorites"][i]);

    }
    print(favoritesId);

  }

  }

  Future<dynamic> _makeFavoriteList() async{

    Future.delayed(Duration(seconds: 1));

    for(int i =0; i < favoritesId.length; i++){

     futureBooks = booksRef.where("id", isEqualTo: favoritesId[i]).getDocuments();

    }

    print(futureBooks);

    return futureBooks;

  }


  @override
  Widget build(BuildContext context) {

    timeDilation = 2.5;

    Widget _buildFavoriteGridItem(context, index){

      return Column(
        children: <Widget>[
          Material(
            elevation: 7.0,
            shadowColor: Colors.blueAccent.shade700,
            child: InkWell(
              onTap: (){
                Navigator.of(context).push(MaterialPageRoute(
                    builder: (context) => DetailScreen()
                ));
              },
              child: Hero(
                tag: index['title'],
                child: Image.network(
                  index["cover"],
                  fit: BoxFit.fill,
                  height: 132,
                  width: 100,
                ),
              ),
            ),
          ),
          Container(
            width: 100,
            margin: EdgeInsets.only(top: 10, bottom: 5),
            child: Text(index["title"],
              textAlign: TextAlign.center,
              overflow: TextOverflow.ellipsis,
              maxLines: 2,
              style: TextStyle(
                fontSize: 10,
                fontWeight: FontWeight.w900,

              ),
            ),
          ),
        ],
      );
    }

    return Scaffold(
      drawer: CustomDrawer(),
      appBar: AppBar(
        title: Text("Favoritos"),
        centerTitle: true,
        elevation: 0,
        /*actions: <Widget>[
          IconButton(
              icon: Icon(Icons.search),
              onPressed: () async {

                showSearch(context: context, delegate: DataSearch());

              }
          )
        ],*/
      ),

      body: Stack(
        children: <Widget>[
          FutureBuilder(
            future: _makeFavoriteList,
            builder: (context, snapshot){
              if(snapshot.hasData){
                return GridView.builder(
                  padding: EdgeInsets.fromLTRB(16, 16, 16, 16),
                  primary: false,
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 3,
                    childAspectRatio: MediaQuery.of(context).size.width /
                        (MediaQuery.of(context).size.height),
                    //crossAxisSpacing: 3,
                    //mainAxisSpacing: 3
                  ),
                  itemBuilder: (context, index){
                    return _buildFavoriteGridItem(context, snapshot[index]);
                  },
                );

              } else {
                return Container(
                  color: Colors.red,
                );
              }
            },

          ),

        ],
      )


    );

  }

}

2 answers

1

I believe one way to do it would be:

For that you should change the statement of futureBook to an empty list. List()

Future<dynamic> _makeFavoriteList() async{

    Future.delayed(Duration(seconds: 1));

    for(int i =0; i < favoritesId.length; i++){

        List<DocumentSnapshot> futureBooks = List();

        futureBooks.add(await booksRef.document(id).get());

    }

    print(futureBooks.toList().toString());

    return futureBooks;

}

The loop will repeat by adding only favorite books to the list. I can’t test it so comment on something, everything indicates it should work.

1

A complication that exists when using the firestore is to perform the JOINS of life... The way you did is an exit to the problem, you just need to perform some small modifications.

As you already own the Ids of all favorite books, it is not necessary to perform a where to bring the Documents with the data of the books, just you access them directly by your ID.

Future<dynamic> _makeFavoriteList() async{
  Future.delayed(Duration(seconds: 1));

  List<DocumentSnapshot> books = [];

  for(int i =0; i < favoritesId.length; i++){
    book = await booksRef.document(favoritesId[i]).get();
    books.add(book);
  }

  return books;
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.