Flutter中API请求后Flip Widget数据更新延迟问题求助
问题原因
- 变量初始为空,没有占位内容,导致Widget启动后无数据可显示
- 两个API请求串行执行,且
fetchPrayerTime中直接依赖未完成的prayerTimeNexDay请求,导致延迟 - 异步请求完成后才更新状态,初始化阶段没有过渡展示
解决方案
1. 设置初始占位值
初始化变量时赋予合理默认值,避免启动时空白:
String cPrayerName = "加载中..."; String cPrayerTime = "--:--:--"; Duration remingTime = Duration.zero;
2. 并行执行API请求+统一更新状态
将两个请求并行执行,确保数据就绪后再计算展示内容:
@override void initState() { super.initState(); _loadAllPrayerData(); } // 并行加载所有祈祷时间数据 Future _loadAllPrayerData() async { await Future.wait([ fetchPrayerTime(), fetchPrayerTimeNExDay(), ]); // 数据全部加载完成后计算当前展示内容 _calculateCurrentPrayer(); } // 抽离判断逻辑为独立方法 void _calculateCurrentPrayer() { if (prayerTime.isEmpty || prayerTimeNexDay.isEmpty) return; DateTime now = DateTime.now(); DateTime fajirTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse( "${DateTime.now().toString().substring(0, 10)} ${prayerTime[0].fajir}"); DateTime dhuhrTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse( "${DateTime.now().toString().substring(0, 10)} ${prayerTime[0].dhuhar}"); DateTime asrTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse( "${DateTime.now().toString().substring(0, 10)} ${prayerTime[0].asr}"); DateTime magribTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse( "${DateTime.now().toString().substring(0, 10)} ${prayerTime[0].magrib}"); DateTime ishaTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse( "${DateTime.now().toString().substring(0, 10)} ${prayerTime[0].isha}"); DateTime nextDayFajirTime = DateFormat("yyyy-MM-dd HH:mm:ss").parse( "${DateTime.now().add(Duration(days:1)).toString().substring(0, 10)} ${prayerTimeNexDay[0].fajir}"); setState(() { if (now.isBefore(fajirTime)) { cPrayerName = "Fajr"; cPrayerTime = DateFormat.Hms().format(fajirTime); remingTime = fajirTime.difference(now); } else if (now.isAfter(fajirTime) && now.isBefore(dhuhrTime)) { cPrayerName = "Duhur"; cPrayerTime = DateFormat.Hms().format(dhuhrTime); remingTime = dhuhrTime.difference(now); } else if (now.isAfter(dhuhrTime) && now.isBefore(asrTime)) { cPrayerName = "Asr"; cPrayerTime = DateFormat.Hms().format(asrTime); remingTime = asrTime.difference(now); } else if (now.isAfter(asrTime) && now.isBefore(magribTime)) { cPrayerName = "Magrib"; cPrayerTime = DateFormat.Hms().format(magribTime); remingTime = magribTime.difference(now); } else if (now.isAfter(magribTime) && now.isBefore(ishaTime)) { cPrayerName = "Isha"; cPrayerTime = DateFormat.Hms().format(ishaTime); remingTime = ishaTime.difference(now); } else { cPrayerName = "Fajr"; cPrayerTime = DateFormat.Hms().format(nextDayFajirTime); remingTime = nextDayFajirTime.difference(now); } }); } // 修改fetchPrayerTime,移除内部状态更新和判断逻辑 Future fetchPrayerTime() async { String year = DateTime.now().year.toString(); String month = DateTime.now().month.toString().padLeft(2, '0'); String day = DateTime.now().day.toString().padLeft(2, '0'); setState(() { currentDate = "$year-$month-$day"; }); Response response = await dio.get("http://localhost/api/prayer-time/get/$currentDate"); if (response.data["data"] != null) { prayerTime.add(PrayerTimeClass.fromJson(response.data["data"])); } } // 修正fetchPrayerTimeNExDay的日期计算 Future fetchPrayerTimeNExDay() async { DateTime nextDay = DateTime.now().add(Duration(days:1)); String year = nextDay.year.toString(); String month = nextDay.month.toString().padLeft(2, '0'); String day = nextDay.day.toString().padLeft(2, '0'); setState(() { nextDayDate = "$year-$month-$day"; }); Response response = await dio.get("http://52.90.175.175/api/prayer-time/get/$nextDayDate"); if (response.data["data"] != null) { prayerTimeNexDay.add(PrayerTimeClass.fromJson(response.data["data"])); } }
3. 用FutureBuilder简化异步状态管理
自动处理加载、成功、失败状态,无需手动管理:
// 包装数据请求为统一Future Future<List<List<PrayerTimeClass>>> _getPrayerData() async { await Future.wait([fetchPrayerTime(), fetchPrayerTimeNExDay()]); return [prayerTime, prayerTimeNexDay]; } @override Widget build(BuildContext context) { return FutureBuilder( future: _getPrayerData(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { // 加载中显示占位Widget return FlipWidget( children: [ Text('加载中...'), Text('剩余时间: --:--:--'), ], ); } else if (snapshot.hasError) { // 请求失败显示错误提示 return Text('加载失败,请重试'); } else { // 数据就绪后计算并展示 _calculateCurrentPrayer(); return FlipWidget( children: [ Text('${cPrayerName} at ${cPrayerTime}'), Text('Remining time : ${remingTime.inHours}:${(remingTime.inMinutes%60).toString().padLeft(2,'0')}:${(remingTime.inSeconds%60).toString().padLeft(2,'0')}'), ], ); } }, ); }
额外优化
- 访问列表元素前先判断是否为空,避免空指针异常
- 格式化剩余时间时补零,提升视觉一致性
- 添加错误重试按钮,增强应用健壮性
内容的提问来源于stack exchange,提问作者Afthal Ad
相关产品推荐
相关产品推荐

