【问题标题】:Initialize App using FutureBuilder with a ListView.builder and have an onClick in each ListItem?使用带有 ListView.builder 的 FutureBuilder 初始化 App 并在每个 ListItem 中有一个 onClick?
【发布时间】:2019-09-24 11:44:25
【问题描述】:

我正在使用 Flutter 构建应用程序,但在使用 FutureBuilder 时遇到问题。情况是我在应用程序中的主页应该向我的服务器发出请求并获取一些 Json。对 getData-Method 的调用发生在主屏幕的构建方法中(不确定这是否正确)。 build-Method 中的下一个调用具有快照并构建一个 ListView。

问题来了:

每次单击按钮或转到不同的屏幕时,都会触发 Future Builder!这意味着我有一堆无用的 API 调用。

问题来了:

我必须改变什么,让 Future Builder 只在我进入主屏幕时运行?

class HomeState extends State<Home> {

  int count = 0;

  final homeScaffoldKey = GlobalKey<ScaffoldState>();

  List compList = new List();

  Future<List> getData() async {
    final response = await http.get(
      Uri.encodeFull("http://10.0.2.2:5000/foruser"),
      headers: {
        "Authorization":
            "JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NTk2NDM4ODcsImlhdCI6MTU1NzA1MTg4NywibmJmIjoxNTU3MDUxODg3LCJpZGVudGl0eSI6MX0.OhuUgX9IIYFX7u0o_6MXlrMYwk7oMCywlmHLw-vbNSY",
        "charset": "utf-8"
      },
    );

    if (response.statusCode == 200) {
      compList = jsonDecode(response.body);
      List<Comp> result = [];
      count++;
      for (var c in compList) {
        Comp comp = Comp.fromJson(c);
        result.add(comp);
      }
      return result;
    } else {
      throw Exception('Failed to load');
    }
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        backgroundColor: Colors.white10,
        body: Stack(
          children: <Widget>[
            new Container(
              child: FutureBuilder(
                future: getData(),
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  if (snapshot.connectionState == ConnectionState.done) {
                    if (snapshot.data == null) {
                      return new Container(
                        child: Text("whoops"),
                      );
                    }
                    if (snapshot.hasData) {
                      if (snapshot.data != null) {
                        if (snapshot.data.toString() == "[]") {
                          print("no comps - called API: $count");
                          return new ListView(
                            key: Key("1"),
                            children: <Widget>[
                              new Column(
                                mainAxisSize: MainAxisSize.max,
                                children: <Widget>[
                                  SizedBox(
                                    height: 30.0,
                                  ),
                                  Card(
                                    color: Colors.blue,
                                    child: Column(
                                      mainAxisSize: MainAxisSize.min,
                                      children: <Widget>[
                                        ListTile(
                                          title: Text(
                                            "Welcome, you have no comps",
                                            style:
                                                TextStyle(color: Colors.white),
                                          ),
                                        ),
                                      ],
                                    ),
                                  ),
                                ],
                              ),
                            ],
                          );
                        }
                        return ListView.builder(
                          itemCount: snapshot.data.length,
                          itemBuilder: (BuildContext context, int index) {
                            print(index);
                            if (index == 0) {
                              return new Column(
                                children: <Widget>[
                                  Card(
                                    color: Colors.blue,
                                    child: Column(
                                      mainAxisSize: MainAxisSize.min,
                                      children: <Widget>[
                                        ListTile(
                                          title: Text(
                                            "Welcome back, these are your comps",
                                            style:
                                                TextStyle(color: Colors.white),
                                          ),
                                        ),
                                      ],
                                    ),
                                  ),
                                  SizedBox(
                                    height: 10.0,
                                  ),
                                  new CompListItem(
                                      new Comp(
                                        snapshot.data[index].left_name,
                                        snapshot.data[index].right_name,
                                        snapshot.data[index].left,
                                        snapshot.data[index].right,
                                        snapshot.data[index].left_city,
                                        snapshot.data[index].right_city,
                                        snapshot.data[index].latitude_left,
                                        snapshot.data[index].longitude_left,
                                        snapshot.data[index].latitude_right,
                                        snapshot.data[index].longitude_right,
                                        snapshot.data[index].points,
                                      ),
                                      "left")
                                ],
                              );
                            }
                            Comp tmp = new Comp(
                              snapshot.data[index].left_name,
                              snapshot.data[index].right_name,
                              snapshot.data[index].left,
                              snapshot.data[index].right,
                              snapshot.data[index].left_city,
                              snapshot.data[index].right_city,
                              snapshot.data[index].latitude_left,
                              snapshot.data[index].longitude_left,
                              snapshot.data[index].latitude_right,
                              snapshot.data[index].longitude_right,
                              snapshot.data[index].points,
                            );
                            return new CompListItem(tmp, "left");
                          },
                        );
                      } else if (snapshot.data == null) {
                        return new Container(
                          child: Text("Sorry, there seems to be a problem :("),
                        );
                      }
                    }
                  } else {
                    return CircularProgressIndicator();
                  }
                },
              ),
            ),
          ],
        ),
        floatingActionButton: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            FloatingActionButton(
              heroTag: null,
              child: Icon(
                Icons.add_location,
                color: Colors.white,
              ),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => MakeComp(),
                  ),
                );
              },
              backgroundColor: Colors.blue,
            ),
            SizedBox(
              height: 10.0,
            ),
            FloatingActionButton(
              heroTag: null,
              child: Icon(Icons.compare_arrows),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => GetComps(),
                  ),
                );
              },
              backgroundColor: Colors.blue,
            ),
          ],
        ));
  }
}

实际结果:

打开应用程序 -> Future Builder 运行 -> 显示数据列表 -> 导航到另一个 Widget -> Future Builder 运行 -> 单击某个按钮 -> Future Builder 运行

预期结果:

打开应用程序 -> Future Builder 运行 -> 显示数据列表 -> 导航到另一个 Widget -> 单击某个按钮 -> 在另一个屏幕上做某事 -> 返回主屏幕 -> Future Builder 运行

【问题讨论】:

    标签: asynchronous flutter state future


    【解决方案1】:

    在我发布这个问题的那一刻,我找到了答案:D

    感谢 Rémi Rousselet,他在这里回答了这个问题:

    How to deal with unwanted widget build?

    答案很简单,就是将 Future 的调用放入 initState 方法中,当我需要加载数据时,该方法会被准确调用。

    祝大家飞翔快乐!

    【讨论】:

      猜你喜欢
      • 2014-10-10
      • 2021-12-23
      • 2021-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-02
      • 1970-01-01
      • 2021-01-07
      相关资源
      最近更新 更多