【问题标题】:How to call setState alongside FutureBuilder in flutter without resetting the ExpansionTile?如何在不重置ExpansionTile的情况下与FutureBuilder一起调用setState?
【发布时间】:2020-07-29 08:41:12
【问题描述】:

在每个ExpansionTile 内部,我必须调用FutureBuilder 从服务器获取动态数据。 Future Builder 仅在 Expanded 时触发,以便将动态数据显示为 ExpansionTile 的子项。

 ListView(
    padding: EdgeInsets.all(16),
    children: widget.list.map((item) {
      return Card(
        elevation: 5,
        shape: RoundedRectangleBorder(
          side: BorderSide(color: Colors.white70, width: 1),
          borderRadius: BorderRadius.circular(10),
        ),
        child: ExpansionTile(
          leading: Icon(
            item["status"] != 3 ? Icons.warning : Icons.verified_user,
            color: item["status"] != 3 ? Colors.yellow[900] : Colors.green,
          ),
          title: Text(item["service_type"]),
          subtitle: Text(DateFormat('dd MMMM yyyy')
              .format(DateTime.parse(item["created_at"]))
              .toString()),
          onExpansionChanged: (value) {
            setState(() {
              timelineValue = value;
            });
          },
          children: <Widget>[
            timelineValue
                ? FutureBuilder(
                    future: getTimeline(timelineValue, item["id"]),
                    builder:
                        (BuildContext context, AsyncSnapshot snapshot) {
                      if (snapshot.hasData) {
                        // print(jsonDecode(snapshot.data.body).runtimeType);
                        Map map = jsonDecode(snapshot.data.body);
                        var currentstatus =
                            CurrentStatusModel.fromJson(map);
                        return Card(
                          shape: RoundedRectangleBorder(
                            side:
                                BorderSide(color: Colors.white70, width: 1),
                            borderRadius: BorderRadius.circular(10),
                          ),
                          child: Container(
                            decoration: BoxDecoration(
                                borderRadius: BorderRadius.circular(10),
                                color: secondaryColour),
                            height: 250,
                            padding:
                                EdgeInsets.only(top: 8, right: 8, left: 8),
                            child: SingleChildScrollView(
                              child: Column(
                                children: <Widget>[
                                  getTimelinetile(
                                      heading: "ഫോം ലഭിച്ചു.",
                                      subtitle:
                                          "സേവനത്തിനായുള്ള നിങ്ങളുടെ അപേക്ഷ ലഭിച്ചു.",
                                      isFirst: true,
                                      isLast: false,
                                      side: "left",
                                      isInactive: false),
                                  currentstatus.isProcessing == 1
                                      ? getTimelinetile(
                                          heading: "പ്രോസസ്സിംഗ് ആരംഭിച്ചു",
                                          subtitle: currentstatus
                                                      .isProcessingDesc !=
                                                  null
                                              ? currentstatus
                                                  .isProcessingDesc
                                              : "ഞങ്ങളുടെ സ്റ്റാഫുകൾ‌ ഇപ്പോൾ‌ നിങ്ങളുടെ അപ്ലിക്കേഷൻ‌ പരിശോധിക്കുന്നു.",
                                          isFirst: false,
                                          isLast: false,
                                          side: "right",
                                          isInactive: false)
                                      : Container(),
                                  currentstatus.documentsRequired == 1
                                      ? getTimelinetile(
                                          heading: "രേഖകൾ ആവശ്യമാണ്",
                                          subtitle: currentstatus
                                                      .documentsRequiredDesc !=
                                                  null
                                              ? currentstatus
                                                  .documentsRequiredDesc
                                              : "നിങ്ങളുടെ അപേക്ഷയുമായി മുന്നോട്ട് പോകാൻ രേഖകൾ ആവശ്യമാണ്.",
                                          isFirst: false,
                                          isLast: false,
                                          side: "left",
                                          isInactive: false)
                                      : Container(),
                                  currentstatus.documentsRequired == 1
                                      ? getTimelinetile(
                                          heading: currentstatus
                                                      .documentsReceived ==
                                                  1
                                              ? "രേഖകൾ ലഭിച്ചു"
                                              : "രേഖകൾ ഇതുവരെ ലഭ്യമായിട്ടില്ല.",
                                          subtitle: currentstatus
                                                      .documentsReceived ==
                                                  1
                                              ? (currentstatus
                                                          .documentsReceivedDesc !=
                                                      null
                                                  ? currentstatus
                                                      .documentsReceivedDesc
                                                  : "നിങ്ങൾ അയച്ച രേഖകൾ ഇപ്പോൾ ഞങ്ങളുടെ എക്സിക്യൂട്ടീവ് പരിശോധിച്ചുറപ്പിക്കുന്നു.")
                                              : "ഞങ്ങളുടെ സ്റ്റാഫുകൾ നിങ്ങളുടെ ഭാഗത്തു നിന്നുള്ള രേഖകൾക്കായി കാത്തിരിക്കുന്നു.",
                                          isFirst: false,
                                          isLast: false,
                                          side: "right",
                                          isInactive: currentstatus
                                                      .documentsReceived ==
                                                  1
                                              ? false
                                              : true)
                                      : Container(),
                                  currentstatus.paymentRequired == 1
                                      ? getTimelinetile(
                                          heading: "പേയ്‌മെന്റ് ആവശ്യമാണ്.",
                                          subtitle:
                                              "ഞങ്ങളുടെ സേവനവുമായി തുടരാൻ പേയ്‌മെന്റ് ആവശ്യമാണ്.",
                                          isLast: false,
                                          isFirst: false,
                                          side: "left",
                                          isInactive: false,
                                        )
                                      : Container(),
                                  currentstatus.paymentRequired == 1
                                      ? getTimelinetile(
                                          heading: currentstatus
                                                      .paymentReceived ==
                                                  1
                                              ? "പേയ്മെന്റ് ലഭിച്ചു"
                                              : "പേയ്‌മെന്റ് ഇതുവരെ ലഭിച്ചിട്ടില്ല.",
                                          subtitle: "test",
                                          isFirst: false,
                                          isLast: false,
                                          side: "right",
                                          isInactive: currentstatus
                                                      .paymentReceived ==
                                                  1
                                              ? false
                                              : true)
                                      : Container(),
                                  getTimelinetile(
                                      heading: currentstatus.formFinished ==
                                              1
                                          ? "സേവനം പൂർത്തിയായി"
                                          : "സേവനം പൂർത്തീകരിച്ചിട്ടില്ല",
                                      subtitle: currentstatus
                                                  .formFinished ==
                                              1
                                          ? "നിങ്ങളുടെ അപ്ലിക്കേഷൻ ഇതുവരെ പൂർത്തീകരിച്ചിട്ടില്ല."
                                          : "നിങ്ങളുടെ അപ്ലിക്കേഷൻ ഇതുവരെ പൂർത്തിയായിട്ടില്ല.",
                                      isLast: true,
                                      isFirst: false,
                                      side: "left",
                                      isInactive:
                                          currentstatus.formFinished == 1
                                              ? false
                                              : true),
                                  Card(
                                    color: Colors.grey[900],
                                    shape: RoundedRectangleBorder(
                                      side: BorderSide(
                                          color: Colors.white70, width: 1),
                                      borderRadius:
                                          BorderRadius.circular(10),
                                    ),
                                    margin: EdgeInsets.all(20.0),
                                    child: Container(
                                      child: Column(
                                        children: <Widget>[
                                          ListTile(
                                            title: Text(
                                              'example',
                                              style: TextStyle(
                                                  fontSize: 18,
                                                  color: Colors.white),
                                            ),
                                          ),
                                        ],
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        );
                      }
                      if (snapshot.hasError) {
                        return Container();
                      }
                      return Container(
                          height: 30.0,
                          child: LoadingIndicator(
                            indicatorType: Indicator.ballBeat,
                            color: primaryColour,
                          ));
                    })
                : Container()
          ],
        ),
      );
    }).toList(),
  ),

未来的功能是 -

Future getTimeline(value, id) async {
    if (timelineValue == true) {
      return await http.get(
          "http://" + restEndpoint + "/akshaya/public/api/get_timeline/$id");
    }
  }

问题在于每个onExpansionChange 都会调用setState,这会重建小部件树并弄乱ExpansionTile 的当前状态。具体来说,当折叠一个 ExpansionTile 时,每个其他 ExpansionTile 的子代都会折叠,尾随按钮指向展开模式。

【问题讨论】:

  • 请正确复制您的代码。有打开的标签和缺少的闭包,很难理解和帮助你。另外,您能否更明确地解释一下您的最后一段?由于setStates 和未来的构建器,您的小部件是否正在循环重建?
  • 不,它没有循环播放。 ExpansionTiles 的数量是动态的,并且在我使用FutureBuilder 的http get 方法之后再次接收到每个ExpansionTile 的扩展主体(子项)内的内容。但是,当展开多个ExpansionTiles,然后尝试关闭一个“ExpansionTile”时,每个其他ExpansionTile 的展开主体都会关闭,而展开/折叠按钮仍指向展开方向。当我在 onExpansionChanged 回调中使用 setState 时,问题就发生了。 @JoãoSoares
  • 我只想在 ExpansionTile 展开时触发 FutureBuilder。所以没有setState 我无法触发FutureBuilder。请询问您是否需要更多详细信息,并对英语不好表示抱歉。 @JoãoSoares
  • 我想我现在明白了这个问题,而且我相信我以前见过它。我会尝试在本地复制它。
  • @JoãoSoares 感谢您的回访和您的时间。我希望你能解决它。

标签: flutter asynchronous dart flutter-layout


【解决方案1】:

您的问题似乎是,您有一个变量 timelineValue 用于 每次扩展。

您需要每个图块有一个变量

将另一个布尔属性添加到您的widget.list 拥有的任何类中,并使用当前项目的相应属性而不是您的单个变量。

【讨论】:

    猜你喜欢
    • 2019-01-31
    • 2019-10-31
    • 2018-03-27
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 2022-11-24
    • 2018-08-28
    相关资源
    最近更新 更多