You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Stateful Widget调用sqlite取数函数显示null不更新如何解决?

问题根源

  • getCurrentAssetsData中的SQLite查询是异步IO操作,你直接在build阶段同步调用该函数时,数据库查询还未完成,函数就已经执行结束。你写的return语句仅在.then()回调内部生效,外层函数没有显式返回值,默认返回null,因此Text组件显示null。
  • 控制台能打印出正确值是因为异步回调执行时数据已经返回,但此时UI早已渲染完成,没有触发重新渲染,数据不会自动更新到组件上。

注意:不要在build方法中直接执行异步查询操作,build会随状态刷新频繁触发,会造成大量重复无用的数据库查询,严重影响性能。

修复方案

方案1:预加载所有数据后统一渲染(推荐)

先在State类中新增资产数据缓存,加载coin列表时同步查询每个coin的资产数据,全部加载完成后再刷新UI

class _CoinListState extends State<CoinList> {
  DbHelper helper = DbHelper();
  List<Coin> coins;
  int count=0;
  // 新增缓存Map,key为coin id,value为对应资产展示字符串
  Map<int, String> coinAssetsCache = {};

  // 改造getData方法,用async/await避免回调地狱
  void getData() async {
    await helper.initializeDb();
    final coinResult = await helper.getCoin();
    count = coinResult.length;
    List<Coin> tempCoins = [];
    coinAssetsCache.clear();
    for(int i=0;i<count;i++){
      Coin coin = Coin.fromObject(coinResult[i]);
      tempCoins.add(coin);
      // 逐个查询对应资产数据存入缓存
      String assetsData = await getCurrentAssetsData(coin);
      coinAssetsCache[coin.id] = assetsData;
    }
    // 所有数据加载完成后统一刷新UI
    setState(() {
      coins = tempCoins;
      this.count = count;
    });
  }

  // 改造getCurrentAssetsData为返回Future的异步函数
  Future<String> getCurrentAssetsData(Coin coin) async {
    await helper.initializeDb();
    final orderResult = await helper.getCoinOrder(coin);
    double totalCost = 0;
    double totalCount = 0;
    double totalCommission=0;
    for(int i=0;i<orderResult.length;i++){
      CoinOrder order = CoinOrder.fromObject(orderResult[i]);
      totalCost += order.count * order.buyValue;
      totalCount += order.count;
      totalCommission+= order.commission;
    }
    String sData = "Avg: ${totalCost/totalCount} Investment: ${totalCost}";
    debugPrint(sData);
    return sData;
  }

  // 修改Text组件取值逻辑,从缓存中取数据
  title: Text(this.coins[position].coin.toString() + " Temp Data " + (coinAssetsCache[this.coins[position].id] ?? "加载中...")),
}

方案2:用FutureBuilder逐行加载

如果不需要等所有数据加载完成再显示列表,可以给每个列表项单独套FutureBuilder实现逐行加载:

// 把原title的Text组件替换为FutureBuilder
title: FutureBuilder<String>(
  future: getCurrentAssetsData(this.coins[position]),
  builder: (context, snapshot) {
    if(snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
      return Text(this.coins[position].coin.toString() + " Temp Data " + snapshot.data!);
    } else if(snapshot.hasError) {
      return Text(this.coins[position].coin.toString() + " Temp Data 加载失败");
    }
    return Text(this.coins[position].coin.toString() + " Temp Data 加载中...");
  },
),

内容的提问来源于stack exchange,提问作者uday

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 20:15:04