Home > database >  How to update list with the result of a function in Flutter?
How to update list with the result of a function in Flutter?

Time:09-03

I'm a beginner in flutter. Here I want to create a ListView.builder

ListView.builder(
           shrinkWrap: true,
           itemCount: filterMangaList.length,
           itemBuilder: (context, index) {
             return ListTile(
                 title: Text(filterMangaList[index]['title']),
                 );
           },
         ),

where filterMangaList looks like this [[{total_chapter: 361, pic: https://images.pexels.com/photos/213780/pexels-photo-213780.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500, title: My Hero Academia}], [{total_chapter: 700, pic: https://images.pexels.com/photos/213780/pexels-photo-213780.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500, title: Naruto}]].

I obtain filterMangaList with this function

Future getFavMangas() async {
    final favMangasList =
        await firestore.collection("users").doc(user.uid).get().then((value) {
      return value.data()?["fav_manga"];
    });

    for (var i in favMangasList) {
      final mangas = await FirebaseFirestore.instance
          .collection('mangas')
          .where('title', isEqualTo: i)
          .get();
      final filterManga = mangas.docs.map((doc) => doc.data()).toList();
      filterMangaList.add(filterManga);
      setState(() {
        filterMangaList;
      });
    }
    print(filterMangaList);}

but nothing append. I know it's a problem of scop, because when i print filterMangaList in my initState, it's empty, but i don't know how to resolve it. The value of filterMangaList is not update with the result of the function. I try replace setState to a return, but the same.

Here my full code


import 'dart:convert';

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:mugiwarapp/init_profil.dart';

class ProfilPage extends StatefulWidget {
  ProfilPage({Key? key}) : super(key: key);

  @override
  State<ProfilPage> createState() => _ProfilPageState();
}

class _ProfilPageState extends State<ProfilPage> {
  FirebaseFirestore firestore = FirebaseFirestore.instance;
  List favMangasList = [];

  List filterMangaList = [];
  @override
  void initState() {
    getFavMangas();
    print(filterMangaList);
    super.initState();
  }

  Future getFavMangas() async {
    final favMangasList =
        await firestore.collection("users").doc(user.uid).get().then((value) {
      return value.data()?["fav_manga"];
    });

    for (var i in favMangasList) {
      final mangas = await FirebaseFirestore.instance
          .collection('mangas')
          .where('title', isEqualTo: i)
          .get();
      final filterManga = mangas.docs.map((doc) => doc.data()).toList();
      filterMangaList.add(filterManga);
      setState(() {
        filterMangaList;
      });
    }
    print(filterMangaList);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Padding(
      padding: const EdgeInsets.only(left: 30, right: 30),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const SizedBox(
            height: 40,
          ),

          Row(
            mainAxisAlignment: MainAxisAlignment.start,
            children: [
              // IconButton(
              //     onPressed: () {
              //       Navigator.pop(context);
              //     },
              //     icon: const Icon(Icons.arrow_back)),
              const Text(
                "Profil",
                style: TextStyle(
                    color: Colors.white,
                    fontSize: 30,
                    fontWeight: FontWeight.bold),
              ),
              TextButton(
                  onPressed: () {},
                  child: const Text(
                    "Editer",
                    style: TextStyle(color: Colors.white),
                  ))
            ],
          ),
          const SizedBox(
            height: 40,
          ),
          Row(children: [
            Column(children: [
              const SizedBox(
                  width: 160,
                  child: Text("Pseudo",
                      textAlign: TextAlign.start,
                      style: TextStyle(
                          color: Colors.white,
                          fontSize: 25,
                          fontWeight: FontWeight.bold))),
              const SizedBox(
                height: 10,
              ),
              SizedBox(
                  width: 160,
                  child: Row(children: const [
                    Text(
                      "Membre depuis ",
                      style: TextStyle(fontSize: 11),
                    ),
                    Text(
                      "Janvier 2021",
                      style:
                          TextStyle(fontSize: 11, fontWeight: FontWeight.bold),
                    )
                  ])),
              const SizedBox(
                height: 15,
              ),
              SizedBox(
                  width: 160,
                  child: Row(children: const [
                    Text(
                      "Manga préféré : ",
                      style: TextStyle(fontSize: 11),
                    ),
                    Text(
                      "Berserk",
                      style:
                          TextStyle(fontSize: 11, fontWeight: FontWeight.bold),
                    )
                  ])),
              SizedBox(
                  width: 160,
                  child: Row(children: const [
                    Text(
                      "Anime préféré : ",
                      style: TextStyle(fontSize: 11),
                    ),
                    Text(
                      "One Piece",
                      style:
                          TextStyle(fontSize: 11, fontWeight: FontWeight.bold),
                    )
                  ])),
              const SizedBox(
                height: 10,
              ),
              SizedBox(
                  width: 160,
                  child: Row(children: const [
                    Text(
                      "à jour sur ",
                      style: TextStyle(fontSize: 11),
                    ),
                    Text(
                      "2 ",
                      style:
                          TextStyle(fontSize: 11, fontWeight: FontWeight.bold),
                    ),
                    Text(
                      "mangas",
                      style: TextStyle(
                        fontSize: 11,
                      ),
                    )
                  ])),
              SizedBox(
                  width: 160,
                  child: Row(children: const [
                    Text(
                      "à jour sur ",
                      style: TextStyle(fontSize: 11),
                    ),
                    Text(
                      "3 ",
                      style:
                          TextStyle(fontSize: 11, fontWeight: FontWeight.bold),
                    ),
                    Text(
                      "animes",
                      style: TextStyle(
                        fontSize: 11,
                      ),
                    )
                  ])),
            ]),
            const SizedBox(
              width: 10,
            ),
            SizedBox(
              height: 125,
              width: 125,
              child: ClipRRect(
                borderRadius: BorderRadius.circular(30),
                child: Image.network(
                  'https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg',
                  fit: BoxFit.fill,
                ),
              ),
            )
          ]),
          const SizedBox(
            height: 50,
          ),
          Text(
            'Recommendations',
            style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
          ),
          // SizedBox(
          //     child: ListView.builder(
          //   physics: ClampingScrollPhysics(),
          //   shrinkWrap: true,
          //   scrollDirection: Axis.horizontal,
          //   itemCount: 3,
          //   itemBuilder: (BuildContext context, int index) {
          //     return ListTile(
          //       title: Text("Titre recommandations"),
          //       tileColor: Colors.red,
          //     );
          //   },
          // )),
          const Text(
            'Continuer à lire',
            style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
          ),
          ListView.builder(
            shrinkWrap: true,
            itemCount: filterMangaList.length,
            itemBuilder: (context, index) {
              return ListTile(
                  title: Text(filterMangaList[index]['title']),
                  );
            },
          ),
        ],
      ),
    ));
  }
}

It's probably a little thing but i can't figure how to solve it. I'm open to all advice. Thanks in advance !

Sorry for my english, french here.

CodePudding user response:

Your problem is in this function:

Future getFavMangas() async {
    final favMangasList =
        await firestore.collection("users").doc(user.uid).get().then((value) {
      return value.data()?["fav_manga"];
    });

    for (var i in favMangasList) {
      final mangas = await FirebaseFirestore.instance
          .collection('mangas')
          .where('title', isEqualTo: i)
          .get();
      final filterManga = mangas.docs.map((doc) => doc.data()).toList();
      filterMangaList.add(filterManga);
      setState(() {
        filterMangaList;
      });
    }
    print(filterMangaList);
  }

when you call return value.data()?["fav_manga"] function break and wont go for other code in that function, So change it to this:

Future getFavMangas() async {
    var value =
        await firestore.collection("users").doc(user.uid).get()
    final favMangasList = value.data()?["fav_manga"];
        

    for (var i in favMangasList) {
      final mangas = await FirebaseFirestore.instance
          .collection('mangas')
          .where('title', isEqualTo: i)
          .get();
      final filterManga = mangas.docs.map((doc) => doc.data()).toList();
      filterMangaList.add(filterManga);
      setState(() {
        filterMangaList;
      });
    }
    print(filterMangaList);
  }

Update:It is not ok to use async function inside initState, so you should use FutureBuilder, wrap your sacffold's body with FutureBuilder like this:

body: FutureBuilder<List>(
      future: getFavMangas(),
      builder: (context, snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.waiting:
            return Text('Loading....');
          default:
            if (snapshot.hasError) {
              return Text('Error: ${snapshot.error}');
            } else {
              List data = snapshot.data ?? [];
             
              return Padding(
                 ....(rest of the widgets)
                 ListView.builder(
                  itemBuilder: (context, index) {
                    return Column(children: [
                      Text(data[index]['title'] ?? ""),
                    ]);
                  },
                  itemCount: data.length,
                ),
              );
            }
        }
      },
    ),

CodePudding user response:

Ok, so for those who want to know the answer. I used a FutureBuilder like this

FutureBuilder(
              future: getFavMangas(),
              builder: (context, AsyncSnapshot future) {
                if (!future.hasData)
                  return Container();
                else {
                  var filterMangaList = future.data;
                  print(filterMangaList);
                  return ListView.builder(
                    shrinkWrap: true,
                    itemCount: filterMangaList.length,
                    itemBuilder: (BuildContext context, int index) {
                      return Container(
                        child: Text(filterMangaList.toString()),
                      );
                    },
                  );
                }
              }),

(the ListView.builder is not finish)

but here, I had an infinite loop. So I change the setState to a return in my function and change the type to List

Future<List> getFavMangas() async {
    var value = await firestore.collection("users").doc(user.uid).get();
    final favMangasList = value.data()?["fav_manga"];
    filterMangaList.clear();

    for (var i in favMangasList) {
      final mangas = await FirebaseFirestore.instance
          .collection('mangas')
          .where('title', isEqualTo: i)
          .get();
      final filterManga = mangas.docs.map((doc) => doc.data()).toList();
      filterMangaList.add(filterManga);
    }
    return filterMangaList;
  }

and change my initState to this

late Future<List<dynamic>> _filterMangaList;

  @override
  void initState() {
    _filterMangaList = getFavMangas();
    super.initState();
  }

so in result I have all my filterMangaList that is displaied, like I wanted (for now).

Not clean I think but it works !

  • Related