Flutter:嵌套异步HTTP调用的最佳做法

时间:2018-07-09 12:50:58

标签: flutter

我正在尝试将两个Http请求的结果加载到列表项中(第二个请求是有关第一个请求结果项的详细信息)。 第一个请求获取加密货币列表。 第二个请求收集有关该货币的更多信息。

enter image description here

我想在两个单独的请求中完成此操作的原因是

  1. 数据来自不同的来源。
  2. 获得货币清单后,我想显示一个流程圆圈,这表示“保持冷静,细节在加载”

我已经尝试过的是

  • 一个带有两个方法的有状态小部件(都在调用setState)是灾难性的。无限循环。

  • build方法中的一个基本状态小部件和第二个子状态小部件。工作正常,但是每当我向上或向下滚动时,列表都会重新呈现其项目,并且子状态小部件会一次又一次发出相同的getPrice HTTP请求。

  • 一个继承小部件和一个无状态小部件。必须将上下文用于两个HTTP请求方法。它再次导致了无休止的循环。

目前,我的大脑中有一部分人大喊“ Redux是唯一以适当方式处理此问题的方法”

您对此有何建议? 预先谢谢你。

2 个答案:

答案 0 :(得分:0)

您可以轻松使用FutureBuilder。我将在这里写下一些评论。我希望这是可以理解的:

ListView.builder(
  ...
  builder: (BuildContext context, int index) {
    // I am just using this builder to symbolize where each list item starts
    // there is no styling here, just a Container with full width and some height, which is like an ugly Card
    return Container(
      color: Colors.yellow,
      width: double.infinity,
      height: 300.0,
      child: Row(
        // the first child symbolizes the currency name from your illustration
        // the second child are the numbers, which are not aligned to the right, but I want to keep the code short
        children: <Wigdet>[
          FutureBuilder(
            future: currencyName(index: index),
            builder: (BuildContext context, AsyncSnapshot<String> futureResult) => futureResult.hasData ? Text(futureResult.data) : CircularProgressIndicator(),
           ),
           FutureBuilder(
            future: currencyAmount(imdex: index),
            builder: (BuildContext context, AsyncSnapshot<String> futureResult) => futureResult.hasData ? Text(futureResult.data.toString) : CircularProgressIndicator(),
           ),
         ],
      ),
    );
  },
);

或者,您也可以首先使用FutureBuilder加载所有货币名称,使ListView为该货币的子代,然后像这样使用它们。

我的回答很抽象。我只是找不到更具体的方式来回答您的一般问题。如果您的服务器请求未返回类似的Future,则可能需要在此处重组代码,重组我的答案或完全放弃我的答案。

答案 1 :(得分:0)

void getOwnedCoins() async {
CoinsList cList = await ResourceCoins().list();
setState(() {
  list = cList;
  items = cList.result.length;
});
getCoinSummary(cList);
}

void getCoinSummary(CoinsList coins) {
coins.result.forEach((Coin coin) async {
  CoinSummary cs = await ResourceCoinSummary().summary(market: {'market': 'btc-' + coin.currency});
  coin.summary = cs;

  setState(() {
    list = coins;
  });
});
}

这就是我解决的方法。我的错误是在ListView.builder中调用 getCoinSummary 。但是,我对 getCoinSummary 中的setState感到不满意。每次从服务器获取详细信息时,我都会重新渲染整个列表。应该是这样吗?