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

Flutter iOS release版didChangeAppLifecycleState触发时网络API请求失败求助

问题根因

  • iOS系统对进入paused状态的应用后台执行时间做了严格限制,release模式下默认仅预留约3-5秒的收尾时间,超时后应用会被系统强制挂起,所有未完成的异步任务(包括Web API请求)都会被中断。debug模式下系统会放宽后台限制,所以测试时不会复现,Android的后台生命周期策略相对宽松,因此不会出现该问题。
  • 现有代码逻辑问题:AppLifecycleState.paused回调中执行的scheduleRemindersInBackground方法依赖网络请求,未申请额外后台运行时间,且回调中未等待异步任务执行完成就进入了挂起流程,进一步放大了超时概率。
  • 逻辑设计缺陷:后台场景下优先走网络请求的策略不符合iOS后台运行的特性,离线模式直接读本地DB耗时极短能在超时前完成,在线模式的网络请求大概率超时中断。

修复方案

1. 申请iOS后台运行时间

进入paused状态时,调用iOS后台任务申请接口延长应用运行时间,保证关键任务能完成,可通过在iOS原生层注册后台任务实现,也可直接使用封装好的Flutter插件处理逻辑。

2. 调整paused回调的异步等待逻辑

现有代码中AuraPreferences.queryPreference用了.then没有被await,导致paused回调执行完后系统直接挂起应用,异步任务还没跑完,调整代码如下:

@override
void didChangeAppLifecycleState(AppLifecycleState state) async {
  super.didChangeAppLifecycleState(state);
  switch (state) {
    case AppLifecycleState.paused: 
      // 申请后台任务,iOS端需提前注册对应任务标识
      final taskId = await iOSBackgroundTask.beginBackgroundTask(expirationHandler: () {
        // 后台时间快到的时候手动结束任务,避免被系统杀死
        iOSBackgroundTask.endBackgroundTask(taskId);
      });
      
      // 改为await执行所有关键异步任务
      final value = await AuraPreferences.queryPreference('AppointmentRemindMe');
      if (appState.isUserLoggedIn && AuraConvert.toBoolean(value)) {
        AppointmentReminder.stop();
        await AppointmentReminder.scheduleRemindersInBackground();
      }

      ProgressNoteService.stop();
      chatMessageProvider.stopConnection();

      _goneToBackgroundAt = DateTime.now().toUtc();

      appState.cancelSsoTimer();

      print('App went to background at $_goneToBackgroundAt');
      
      // 任务执行完成后结束后台任务
      await iOSBackgroundTask.endBackgroundTask(taskId);
      break;

    case AppLifecycleState.resumed:
    // 原有resumed逻辑保留

3. 调整数据获取策略适配后台场景

后台执行场景下优先读本地DB数据,避免不必要的网络请求,降低超时概率,修改getAppointments方法:

static Future<List<AuraAppointment>> getAppointments(
  DateTime? dateFrom,
  DateTime? dateTo, {
  isCalledFromCalendar = false,
  isSync = false,
  // 新增后台调用标识
  isBackgroundCall = false,
}) async {
  if (dateFrom == null || dateTo == null) return <AuraAppointment>[];

  final authUser = await UserService.authUser;
  final localDb = await MobileDatabase.dbInstance;
  
  // 后台调用优先读本地数据,不走网络请求
  if (isBackgroundCall) {
    final localAppointments = (await localDb.query(
      'AuraAppointments',
      where: 'OwnerID = ?',
      whereArgs: [authUser?.userId],
    )).map((i) => AuraAppointment.fromMap(i)).toList();
    // 过滤出时间范围内的数据直接返回
    return localAppointments.where((a) => a.startTime.isAfter(dateFrom) && a.startTime.isBefore(dateTo)).toList();
  }
  
  // 原有前台逻辑保持不变
  final String uri = 'https://api.domain123.com/something_here_to_send_parameters';
  final networkHelper = NetworkHelper(uri, authUser: authUser, goToLoginScreen: isCalledFromCalendar);
  // ... 剩余原有逻辑保留
}

调用时传入后台标识:

static Future<void> scheduleRemindersInBackground() async {
  final appointments = await ScheduleService.getAppointmentReminders(
    inNextMinutes: 60 * 24 * 3,
    isBackgroundCall: true,
  );
  for (int i = 0; i < appointments.length; i++) {
    await _scheduleReminderInBackground(
    // 原有逻辑保留

4. Xcode配置检查

打开Xcode项目,在Signing & Capabilities中添加Background Modes能力,勾选Background fetch和Remote notifications选项,确保系统允许应用执行后台相关任务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 00:54:03