Flutter - iterate over an asynchrous/future list

1,504

Solution 1

Why causing this problem?

Future<List> sportsList() async {
    List sports=[
      await initSharedPreference("test")), 
        ....,
        ....,
        ....
    ];
  }

The above code is not a simple list where the list can be directly rendered. It's returning Future<List> which must be fetched as background work. So Use FutureBuilder for it.

FutureBuilder is a one-time call which will run only ones during its lifecycle. So you can rely on it.

FutureBuilder(
            future: sportsList(),
            builder: (context, snapshot) {
              if (!snapshot.hasData) {
                return CircularProgressIndicator();
              } else {
                List<Widget> list = snapshot.data;
                return CarouselSlider(
                     options: CarouselOptions(
                     height: 565,
                     aspectRatio: 16/9,
                     enlargeCenterPage: true,
                     viewportFraction: .8,
                    ),
                      items: list.map(.....).toList(),
                       
                    );
              }
            })

Solution 2

You need to use a FutureBuilder like this..

FutureBuilder(
            future: sportsList(),
            builder: (context, snapshot) {
              if (!snapshot.hasData) {
                return CircularProgressIndicator();
              } else {
                return CarouselSlider(
                       items: snapshot.data.map(.....).toList(),
                       //other code
                    );
              }
            })

Solution 3

Just use a FutureBuilder widget.

In the following example, my asynchronous function is called getSportsList() which returns a future List of Strings (This could be gotten from SharedPreferences, an API, et cetera. Just make sure it's a future).

class FutureList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    // THE FUTURE WIDGET

    return FutureBuilder<List<String>>(
      future: getSportsList(), // Add your asynchronous function here
      builder: (context, AsyncSnapshot<List<String>> snapshot){

        List<String> sports = snapshot.data;
        // If there is no data in the snapshot, it is probably loading.
        if(!snapshot.hasData) return CircularProgressIndicator(); 
        // Now add the widget you want to return
        else return CarouselSlider(
          options: CarouselOptions(
            height: 565,
            aspectRatio: 16/9,
            enlargeCenterPage: true,
            viewportFraction: .8,
          ),
          items: sportsList.map((String item) {
            return Builder(builder: (BuildContext context) {
              return Container(
                .......
                .........
                .......
      },
    );
  }
}

A snapshot basically gives info about the future. snapshot.data is the result obtained from the future. snapshot.hasData tells us whether the future returned a value or not, and there are a couple of other useful methods like snapshot.connectionState or snapshot.hasError for error handling.

For more resources, check out this video by the flutter team. Also check out the documentation to find out more

Share:
1,504
Jip Harthoorn
Author by

Jip Harthoorn

Updated on December 22, 2022

Comments

  • Jip Harthoorn
    Jip Harthoorn over 1 year

    I'm trying to create a list with values obtained by SharedPreferences. However, if I want to use SharedPreference, I've to use async methods / future types and I have no idea how to work with them. I try to iterate over the sports list, but it is asynchronous/future. So how do I iterate over it (using map)?

    class _MyHomePageState extends State<MyHomePage> {
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            Center(
              child: Align(
                alignment: Alignment.bottomCenter,
                child: CarouselSlider(
                  options: CarouselOptions(
                    height: 565,
                    aspectRatio: 16/9,
                    enlargeCenterPage: true,
                    viewportFraction: .8,
                  ),
                  items: sportsList.map((i) {
                    return Builder(builder: (BuildContext context) {
                      return Container(
                        .......
                        .........
                        .......
    }
    
    
      static Future<bool> initSharedPreference(String key) async {
        final SharedPreferences prefs = await SharedPreferences.getInstance();
        
        return prefs.getBool(key) ?? false;
      }
    
    
      Future<List> sportsList() async {
        List sports=[
          await initSharedPreference("test")), 
            ....,
            ....,
            ....
        ];
      }
    

    This code doesn't work because of the following:

    The method 'map' isn't defined for the type 'Future'.

  • Jitesh Mohite
    Jitesh Mohite almost 4 years
    get data like this List<Widget> list = snapshot.data;