简体   繁体   中英

how to create dynamic list of futures for futurebuilder

I have a longList where I need each element in the list to be sent to a database to return some a sub-list. I then display each value in it's own PageView using PageView.builder. and FutureBuilder .

At first I was setting future: sql(longlist[pageIndex]) to give the future for each element in the PageView. However this is bad because it means the database is queried every time the widget is rebuilt.

So what I want is in the list for each element, call await sql(element) in initState() , and store this in a way the futurebuilder can use it.

Here is the simplified layout of my code:

  final List<Map<String, dynamic>> longList; // <-- eg ["cat", "dog", "mouse", ...]

  late Future<List<Map<String, dynamic>>> exampleFuture;
  Future<List<Map<String, dynamic>>> getUnits(int index) async {
    final data = await SQLHelper.getExamples(longList[0]["foo"]);
    return data;
  }
  @override
  void initState() {
    super.initState();
    exampleFuture = getUnits(0);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView.builder(
        itemCount: widget.longList.length,
        itemBuilder: (context, pageIndex) {
          print(pageIndex);
          return FutureBuilder<List<Map<String, dynamic>>>(
              future: exampleFuture[pageIndex],
              builder: (BuildContext context,
                  AsyncSnapshot<List<Map<String, dynamic>>> snapshot) {
                if (snapshot.hasData) {
                  List<Map<String, dynamic>>? exampleList = snapshot.data;
                  return Column(
                    children:[Text(
                        "this is page $pageIndex with future data "+exampleList[pageIndex];
                    ),]
                  );
                } else {
                  return const Center(child: CircularProgressIndicator());
                }
              }
          );
        },
      ),
    );
  }
}

I tried instead to create a list of futures in the initState but if the list is itself a future I can't add elements to it and if it's not a future (ie. it only holds a reference to each future) it doesn't work with the futurebuilder as a future: parameter. For example I tried:

late List<List<Map<String, dynamic>>> futureList;
void createList() async {
    for (int i = 0; i<widget.longList.length; i++){
      futureList.add(await SQLHelper.getExamples(widget.longList[i]["foo"]));
    }
  }
  void initState() {
    super.initState();
    createList() 
  }

but trying to use it like

return FutureBuilder<List<Map<String, dynamic>>>(
              future: futureList[pageIndex]

didn't work and the futurebuilder thinks the list is empty.

Ideally I'd rather not use Future.wait because I'd like to show the first page immediately without waiting for the rest of the db queries. If that's the only solution I'd like to understand how to use it. I don't get how I would use Future.await here.

You can have a list of futures. It just looks like perhaps you didn't do it correctly. Here's what it might look like:

  final List<Map<String, dynamic>> longList; // <-- eg ["cat", "dog", "mouse", ...]

  late List<Future<List<Map<String, dynamic>>>> futureList;

  Future<List<Map<String, dynamic>>> getUnits(int index) async {
    final data = await SQLHelper.getExamples(longList[0]["foo"]);
    return data;
  }

  @override
  void initState() {
    super.initState();
    futureList = List.generate(widget.longList.length, (i) => getUnits(i));
  }

Note the declaration for futureList : List<Future<...>> , which is a list of futures.

You can also use typedef Unit = List<Map<String, dynamic>> , to make things easier to understand.


typedef Unit = List<Map<String, dynamic>>;
final Unit longList;

//instead of List<List<Unit>>;
late List<Future<Unit>> futureList;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM