【问题标题】:flutter - FutureBuilder auto rebuild each time press a button in the screen颤振 - 每次按下屏幕上的按钮时,FutureBuilder 都会自动重建
【发布时间】:2021-10-15 11:29:19
【问题描述】:

我尝试在 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 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
}

我读过一些文件说我应该在 initState 时将 functionForBuilder() 分配给 Future 变量,然后在 FutureBuilder 的未来子代中使用它。示例:

Future _future;

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

// then with the FutureBuilder
future: _future

通过这种方式,屏幕不再重建,但我的函数 returnRange() 似乎没有像我的预期那样运行(我在 build() 函数中调用了 returnRange() 一次)。

提前感谢您的回答!

【问题讨论】:

  • 请显示完整代码
  • 嗨,我已经编辑了帖子,请看一下。请注意,我还在日历中调用了一次函数 returnRange()。谢谢。

标签: flutter flutter-futurebuilder syncfusion-calendar


【解决方案1】:

每当您再次分配给_future 变量时,您必须在setState 块内执行此操作,否则小部件将不会随着新的未来而重建。

例如:

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

【讨论】:

  • 对不起,我不明白你的意思。我已经在initState() 中分配了_futurefunctionForBuilder。之后,它没有任何变化,我只将_future 作为FutureBuilder(future: _future) 的参数传递。
【解决方案2】:

如果您使用 FutureBuilder,它会一次又一次地重建项目。

尝试两种方法:

  1. 不要使用`future: functionForBuilder(),注释掉。
  2. 删除 FutureBuilder(),只需使用 Container()。

如果有任何问题,请告诉我?

【讨论】:

  • 我需要FutureBuilder 来确保我的功能在build 之前完成,所以我有一个完整的数据可以使用。如果我删除future: functionForBuilder,它将如何检查我的功能是否完成?谢谢
【解决方案3】:

代码:

在 initstate 方法中调用你的未来,而不是在构建中,如示例中所示。

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

【讨论】:

  • 我想我对你的回答做了同样的事情。但我的意思是returnRange() 返回我的日历所需的东西,所以我在build 中调用它一次。对于_future,我只在initState中调用它,然后在FutureBuilder的未来使用它。我认为这与您在回答中所做的相同。
猜你喜欢
  • 2022-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-02
  • 2021-01-21
  • 1970-01-01
  • 1970-01-01
  • 2022-07-19
相关资源
最近更新 更多