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

Flutter中API请求后Flip Widget数据更新延迟问题求助

问题原因

  1. 变量初始为空,没有占位内容,导致Widget启动后无数据可显示
  2. 两个API请求串行执行,且fetchPrayerTime中直接依赖未完成的prayerTimeNexDay请求,导致延迟
  3. 异步请求完成后才更新状态,初始化阶段没有过渡展示

解决方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:40:30