flutter - FutureBuilder автоматически перестраивает каждый раз при нажатии кнопки на экране

Я пытаюсь использовать FutureBuilder во Flutter, чтобы дождаться завершения моего initState, а затем создать пользовательский интерфейс для приложения. Но когда приложение запущено, экран перестраивается каждый раз, когда я нажимаю другую кнопку (кнопка делает совершенно разные вещи).

      Future loadUser() async {
    String jsonString = await storage.read(key: "jwt");
    final jsonResponse = json.decode(jsonString);
    loggedUser = new LoggedUser.fromJson(jsonResponse);
    print(loggedUser.token);
    getProfile();
    getJourneyByUserId()
        .then((receivedList){
      addRanges(receivedList);});
    }

Future<List<Journey>>getJourneyByUserId() async {
    var res = await http.get(
      Uri.parse("$baseUrl/journeys/userid=${loggedUser.user.userId}"),
      headers: {
        'Content_Type': 'application/json; charset=UTF-8',
        'Authorization': 'Bearer ${loggedUser.token}',
      },
    );
    if (res.statusCode == 200) {
      print("Get journeys successfully");
    }
    var data = jsonDecode(res.body);
    List idList = [];
    for (var i in data) {
      idList.add(i["journeyId"]);
    }
    for (var i in idList) {
      var res = await http.get(
        Uri.parse("$baseUrl/journeys/$i"),
      );
      var data = jsonDecode(res.body);
      Journey userJourney = new Journey.fromJson(data);
      setState(() {
        journeyList.add(userJourney);
      });
    }
    print("Journey ${journeyList.length}");
    return journeyList;
  }

addRanges(journeyList){
    setState(() {
      rangeList=[];
    });
      if (journeyList.isNotEmpty) {
        for (var i in journeyList) {
          DateTime startDate =
          DateTime(i.startDate.year, i.startDate.month, i.startDate.day);
          DateTime endDate =
          DateTime(i.endDate.year, i.endDate.month, i.endDate.day);
          setState(() {
            rangeList.add(PickerDateRange(startDate, endDate));
          });
        }
      }
      print("Range ${rangeList.length}");
      return rangeList;
  }

returnRange() {
    List<PickerDateRange> list = [];
    for(int i =0; i<rangeList.length;i++){
      list.add(rangeList[i]);
    }
    return list;
  }

Future functionForBuilder() async {
    return await returnRange();
  }

//initState function
  @override
  void initState() {
    super.initState();
    loadUser();
    functionForBuilder();
  }

//build the UI
Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("$_name's Profile",style: TextStyle(color: kColorPalette4),),
          centerTitle: true,
        ),
        body: Container(
          child: FutureBuilder(
            future: functionForBuilder(),
            builder: (BuildContext context,AsyncSnapshot snapshot){
            //here I set the condition for each case of snapshot
}

Я читал некоторые документы, в которых говорится, что я должен назначить functionForBuilder () переменной Future, когда initState, а затем использовать ее в будущем дочернем элементе FutureBuilder. Пример:

      Future _future;

//initState function
  @override
  void initState() {
    super.initState();
    loadUser();
    _future=functionForBuilder();
  }

// then with the FutureBuilder
future: _future

Таким образом, экран больше не перестраивается, но моя функция returnRange(), похоже, не работает как моя expextation(я вызвал returnRange() один раз в функции build ()).

Заранее благодарим за ответ!

3 ответа

Код:

вызовите свое будущее в методе initstate, а не в сборке, как показано в примере.

class MyPage extends StatefulWidget { @override State<MyPage> createState() => _MyPageState(); } class _MyPageState extends State<MyPage> { // Declare a variable. late final Future<int> _future; @override void initState() { super.initState(); _future = _calculate(); // Assign your Future to it. } // This is your actual Future. Future<int> _calculate() => Future.delayed(Duration(seconds: 3), () => 42); @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder<int>( future: _future, // Use your variable here (not the actual Future) builder: (_, snapshot) { if (snapshot.hasData) return Text('Value = ${snapshot.data!}'); return Text('Loading...'); }, ), ); } }

Всякий раз, когда вы назначаете _future опять же, вы должны сделать это внутри setState block, иначе виджет не перестроится с новым будущим.

Например:

      void updateData() {
  setState(() {
      _future = functionForBuilder();
  });
}

Если вы используете FutureBuilder, он перестраивает элементы снова и снова.

Попробуйте два способа:

  1. Не используйте `future: functionForBuilder(), прокомментируйте это.
  2. Удалите FutureBuilder(), просто используйте Container().

И дайте мне знать о любой проблеме?

Другие вопросы по тегам