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

Flutter/Dart中async/await未等待异步操作完成导致数据初始化异常的解决方法

问题分析

你遇到的核心问题是异步操作的执行顺序错误:initState是同步方法,不能直接使用async/await,所以你在initState里调用getData()后立刻执行doSetup()时,getData()里的异步数据库查询还没完成,导致allSlokamsList还是空数组,进而_init()里的映射构建也失败了。

解决方案

我们需要确保getData()完成数据加载后,再执行依赖这些数据的doSetup()。可以通过封装一个异步初始化方法来实现:

修改后的代码示例

List<String> allSlokamIdsList = [];
List<Slokam> allSlokamsList = [];
Map<String, List<String>> allSlokamsMap = {};
List<String> sungSlokams = [];
var knownSlokams = {'nma': <String>[], 'mpd': <String>[]};
late String currentAksharam;
late String currentVrtham;
var currentPlayerNo = 0;
late String currentSlokam;

@override
void initState() {
  super.initState();
  print('in sadas');
  // 调用封装的异步初始化方法
  _initializeApp();
}

// 封装异步初始化逻辑,确保数据加载完成后再执行后续操作
Future<void> _initializeApp() async {
  await getData(); // 等待数据库查询完成,allSlokamsList被赋值
  doSetup(); // 现在可以安全地执行依赖数据的操作
}

@override
void dispose() {
  player.dispose();
  super.dispose();
}

Future<void> getData() async {
  allSlokamsList = await dbHelper.getSlokams();
  allSlokamIdsList = await dbHelper.getSlokamIds();
  // print(allSlokamsList[1].first_line);
}

void doSetup() {
  _init();
  _getAudioList();
  player.playbackEventStream.listen((event) {
    if (event.processingState == ProcessingState.completed) {
      slokamCompleted();
    }
  });
}

void _init() {
  print('_init');
  isPlaying = false;
  isPaused = false;
  isStopped = true;
  print('allSlokamsList = $allSlokamsList');
  for (var item in allSlokamsList) {
    allSlokamsMap[item.slokam_id] = [
      item.aksharam,
      item.aksharam3,
      item.slokam_text
    ];
  }
  print('allSlokamsMap=$allSlokamsMap');
}

关键改动说明

  1. 新增_initializeApp()异步方法:这个方法可以使用await等待getData()完成,确保allSlokamsList和allSlokamIdsList被正确赋值后,再调用doSetup()。
  2. 调整initState()逻辑:不再直接调用getData()和doSetup(),而是调用封装的异步方法,避免同步方法里的异步操作顺序问题。
  3. 移除doSetup()的async修饰符:因为现在它不需要等待异步操作,只需在数据准备好后同步执行即可。

预期打印结果

修改后,控制台输出顺序会变成:

I/flutter (17648): in sadas
I/flutter (17648): _init
I/flutter (17648): allSlokamsList = [Slokam实例1, Slokam实例2, ...]
I/flutter (17648): allSlokamsMap={slokam_id_1: [aksharam值, aksharam3值, slokam_text值], ...}

额外建议

如果数据库查询耗时较长,建议在初始化过程中显示加载动画(比如CircularProgressIndicator),避免用户看到空白或异常UI。你可以添加一个isLoading状态变量,在_initializeApp()开始时设为true,完成后设为false,然后在build()方法中根据这个状态切换UI。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 00:42:31