Инициализировать приложение с помощью FutureBuilder с ListView.builder и иметь onClick в каждом ListItem? - PullRequest
0 голосов
/ 06 мая 2019

Я создаю приложение с Flutter и у меня возникла проблема с использованием FutureBuilder. Ситуация такова, что моя HomePage в приложении должна сделать запрос на мой сервер и получить Json. Вызов метода getData происходит в методе сборки Homescreen (не уверен, правильно ли это). Следующий вызов в методе сборки имеет моментальный снимок и создает 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 -> Отображается список данных -> Перейдите к другому виджету -> Запускается Future Builder -> нажмите кнопку -> Запускается Future Builder

Ожидаемые результаты:

Откройте приложение -> Запуски Future Builder -> Отображается список данных -> Перейдите к другому виджету -> нажмите на какую-нибудь кнопку -> сделать что-нибудь на другом экране -> вернуться на домашний экран -> Запускается Future Builder

1 Ответ

0 голосов
/ 06 мая 2019

И в тот момент, когда я разместил этот вопрос, я нашел свой ответ: D

Спасибо Rémi Rousselet, который ответил на этот вопрос здесь:

Как бороться с нежелательной сборкой виджетов?

Ответом было просто поместить вызов для Future в метод initState, который вызывается именно тогда, когда мне нужно загрузить данные.

Счастливого порхания всем!

...