Flutter - 在屏幕上按下按钮时,FutureBuilder 自动重建。

时间:2021-08-12 04:19:26

标签: flutter flutter-futurebuilder syncfusion-calendar

我试图在 Flutter 中使用 FutureBuilder 等待 initState 完成后构建应用程序的 UI。但是当应用程序运行时,每次按下另一个按钮(该按钮执行完全不同的操作)屏幕都会重新构建一次。

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 函数
  @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
}

我已经阅读了一些文档,说我应该将函数 ForBuilder() 分配给一个 Future 变量,在 initState 中使用它来代替调用 functionForBuilder()。例如:

Future _future;

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

// then with the FutureBuilder
future: _future

使用这种方式,屏幕不再重新构建了,但是我的函数 returnRange()似乎没有按照我的预期运行(我在 build()函数中调用了一次 returnRange())。

感谢您提供答案!

1 个答案:

答案 0 :(得分:0)

每次重新分配给 _future 变量时,必须在 setState 块内进行,否则小部件将无法使用新的 _future

例如:

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