Flutter - 迭代異步/未來列表 (Flutter - iterate over an asynchrous/future list)


問題描述

Flutter ‑ 迭代異步/未來列表 (Flutter ‑ iterate over an asynchrous/future list)

我正在嘗試使用 SharedPreferences 獲得的值創建一個列表。但是,如果我想使用 SharedPreference,我必須使用異步方法/未來類型,我不知道如何使用它們。我嘗試遍歷 sports 列表,但它是異步的/未來的。那麼我該如何迭代它(使用 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")), 
        ....,
        ....,
        ....
    ];
  }

由於以下原因,此代碼不起作用:

未定義方法“map”對於“未來”類型。


參考解法

方法 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(),

                    );
              }
            })

方法 2:

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

方法 3:

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
                    );
              }
            })

(by Jip HarthoornJitesh MohiteWilson WilsonJigar Patel)

參考文件

  1. Flutter ‑ iterate over an asynchrous/future list (CC BY‑SA 2.5/3.0/4.0)

#dart #Flutter #future #asynchronous






相關問題

如何將數據傳遞給有狀態的小部件 (How to pass data to stateful widget)

顫振無線電值在步進器中沒有改變 (Flutter Radio Value not Changing in Stepper)

如何在顫動中製作響應式播放按鈕? (How to make a responsive play button in flutter?)

如何將數據數組轉換為在顫振/飛鏢中展開或折疊的小部件列表? (How to convert an array of data to a list of widgets with expand or fold in flutter/dart?)

Flutter - 迭代異步/未來列表 (Flutter - iterate over an asynchrous/future list)

使用顫振將圖像作為blob存儲在mysql數據庫中 (Storing image's as blob in mysql database with flutter)

如何在顫動中將視頻播放器浮動在 youtube 等所有頁面上? (How to float a video player over all pages like youtube in flutter?)

無法設置回調函數。錯誤說:“DropDown”必須有一個方法體,因為“ListLayout”不是抽象的 (Unable to set callback function . Error Says: 'DropDown' must have a method body because 'ListLayout' isn't abstract)

Flutter:如何在沒有評級動作的情況下實現評級欄 (Flutter : How to implement rating bar without rating action)

設置狀態內存洩漏 (set state memory leak)

Flutter 視頻播放器不接受自簽名 https 連接 (Flutter video player wont accept self signed https connection)

為什麼有時上下文被替換為下劃線或“_”? (Why sometimes context is being replace as underscore or "_"?)







留言討論