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

使用audio_service重启App后初始化失败:'_cacheManager == null'断言错误

audio_service重启应用后初始化失败问题排查与解决

问题描述

在Flutter应用中使用audio_service实现音频播放功能,用户登出时需要清除缓存并重启应用,但重启后重新初始化audio_service时触发断言错误:

flutter: 'package:audio_service/audio_service.dart': Failed assertion: line 993 pos 12: '_cacheManager == null': is not true.

该错误导致AudioService无法正常初始化。

相关代码片段

触发重启的按钮代码

FilledButton(
  onPressed: () {
    BlocProvider.of<PlayerCubit>(context).clearCache();
    RestartWidget.restartApp(context);
  },
  child: const Text('Restart App'),
),

应用初始化代码

Future<void> runAudioApp() async {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);

  await _initServices();

  runApp(
    const RestartWidget(
      onRestart: _initServices,
      child: AudioApp(),
    ),
  );
}

Future<void> _initServices() async {
  print('RestartWidget _initServices()');
  await di.init();
}

RestartWidget实现

class RestartWidget extends StatefulWidget {
  const RestartWidget({
    required this.onRestart,
    required this.child,
    super.key,
  });

  final Widget child;
  final void Function() onRestart;

  static void restartApp(BuildContext context) {
    context.findAncestorStateOfType<_RestartWidgetState>()?.restartApp();
  }

  @override
  State<RestartWidget> createState() => _RestartWidgetState();
}

class _RestartWidgetState extends State<RestartWidget> {
  Key key = UniqueKey();

  void restartApp() {
    setState(() {
      widget.onRestart.call();
      key = UniqueKey();
    });
  }

  @override
  Widget build(BuildContext context) => KeyedSubtree(
        key: key,
        child: widget.child,
      );
}

依赖注入容器代码

final sl = GetIt.instance;

Future<void> init() async {
  await sl.reset();
  try {
    sl.registerSingleton(AppAudioCache());
    if (!sl.isRegistered<AppAudioHandler>()) {
      try {
        sl.registerSingleton<AppAudioHandler>(
          await initAudioService(audioCache: sl()),
        );
      } catch (e) {
        print(e);
      }
    }
  } catch (e) {
    print(e);
  }
  await sl.allReady();
}

用户疑问:

  • 是否无法在App重启后重新初始化AudioService?
  • 有没有办法彻底销毁旧实例以创建新实例?
  • 当前重启方式是否有误?

解决方案

1. 问题根源

断言错误_cacheManager == null说明audio_service内部的缓存管理器实例未被正确销毁:虽然调用了GetIt的reset(),但audio_service绑定的原生层资源和全局静态状态依然残留;同时当前RestartWidget仅重建Widget树,未等待异步初始化完成就执行重建,导致资源释放不彻底。

2. 主动销毁AudioHandler实例

audio_service的AudioHandler初始化时会绑定原生服务,需主动调用dispose()释放资源,不能仅依赖GetIt重置。修改依赖注入的init()方法:

Future<void> init() async {
  // 先销毁已存在的AudioHandler实例
  if (sl.isRegistered<AppAudioHandler>()) {
    await sl<AppAudioHandler>().dispose();
    sl.unregister<AppAudioHandler>();
  }
  // 重置GetIt容器
  await sl.reset();
  
  try {
    sl.registerSingleton(AppAudioCache());
    // 重新注册AudioHandler
    sl.registerSingleton<AppAudioHandler>(
      await initAudioService(audioCache: sl()),
    );
  } catch (e) {
    print(e);
  }
  await sl.allReady();
}

3. 优化重启逻辑

修改_RestartWidgetState的restartApp方法,确保先完成服务销毁和初始化,再重建Widget:

void restartApp() async {
  // 先执行销毁和初始化操作
  await widget.onRestart();
  // 再更新Key重建Widget树
  setState(() {
    key = UniqueKey();
  });
}

4. 彻底清理缓存

在重启前,除了业务缓存,还需清理audio_service相关缓存:

FilledButton(
  onPressed: () async {
    final playerCubit = BlocProvider.of<PlayerCubit>(context);
    // 清理业务缓存
    playerCubit.clearCache();
    // 清理audio_service缓存
    if (sl.isRegistered<AppAudioCache>()) {
      await sl<AppAudioCache>().clearAll();
    }
    // 重启应用
    RestartWidget.restartApp(context);
  },
  child: const Text('Restart App'),
),

5. 备选:原生级重启

如果上述方法仍无法解决全局状态残留问题,可调用原生平台API彻底重启应用进程:

  • Android:使用SystemNavigator.pop()配合启动页重定向,或第三方插件如flutter_restart
  • iOS:使用exit(0)重启(注意App Store审核限制,仅在必要场景使用)

关键说明

audio_service设计为全局单例服务,不建议频繁销毁重建。登出场景更优方案是:停止播放任务、清理队列和缓存、直接切换到登录页,而非强制重启应用。仅在必须彻底重置所有状态的场景下,再采用上述重启+销毁实例的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:02:48