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

Flutter Android版Release模式启动随机冻结崩溃问题求助

Flutter Android Release模式认证流程随机冻结/崩溃问题解决

问题概述

Flutter Android应用在Release模式(flutter run --release)启动时,认证流程会随机出现冻结或崩溃。日志显示main()函数被调用两次,触发PlatformException(FirebaseApp [DEFAULT]已存在);崩溃场景下,日志在输出user registered: [UID]后停止,怀疑与audio_service依赖有关。

核心问题定位

  1. main()重复执行:部分插件(如audio_service)可能触发应用进程重启或额外初始化流程,导致main()被调用两次,Firebase重复初始化抛出异常。
  2. StreamBuilder嵌套逻辑缺陷:用Stream.fromFuture(registerCurrentUser())包裹异步操作,每次UI重建都会重新执行该Future,且未处理异常,易引发UI阻塞或状态混乱。
  3. getIt单例操作不严谨:异步流程中直接注册/注销单例,多线程或重复执行时可能导致状态不一致。

解决方案

1. 修复Firebase重复初始化

在main()中添加异常捕获,避免重复初始化导致崩溃:

void main() async {
  print("called main");
  WidgetsFlutterBinding.ensureInitialized();
  
  try {
    if (Firebase.apps.isEmpty) {
      await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform,
      );
    }
  } catch (e) {
    print("Firebase初始化异常: $e");
  }
  
  runApp(const App());
}

2. 优化认证流程状态管理

将用户注册逻辑移至initState,用FutureBuilder替代嵌套StreamBuilder,避免重复执行异步操作:

class _AppState extends State<App> {
  Future<bool>? _userRegistrationFuture;

  @override
  void initState() {
    super.initState();
    // 仅初始化一次Future,避免重复执行注册逻辑
    _userRegistrationFuture = registerCurrentUser();
  }

  Future<bool> registerCurrentUser() async {
    print("start registerCurrentUser");
    final user = await FirebaseAuth.instance.currentUser;
    final uid = user?.uid;
    
    // 确保getIt操作原子性
    if (getIt.isRegistered<MyUser>()) {
      getIt.unregister<MyUser>();
    }
    
    if (uid != null) {
      try {
        final DocumentSnapshot doc = await usersRef.doc(uid).get();
        currentUser = MyUser.fromDocument(doc);
        getIt.registerSingleton<MyUser>(currentUser!);
        print('user registered: ${uid}');
      } catch (e) {
        print("用户注册异常: $e");
        return false;
      }
    }
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'audiogaide',
      theme: ThemeData().copyWith(
          useMaterial3: true,
          colorScheme: ColorScheme.fromSeed(
            seedColor: const Color.fromARGB(255, 150, 2, 255),
          )),
      home: StreamBuilder<User?>(
        stream: FirebaseAuth.instance.authStateChanges(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Scaffold(
              body: CircularProgressIndicator(color: Colors.black),
            );
          }

          if (snapshot.hasData) {
            print("has Data");
            return FutureBuilder<bool>(
              future: _userRegistrationFuture,
              builder: ((context, snap) {
                if (snap.connectionState == ConnectionState.waiting) {
                  print("no data yet");
                  return const Scaffold(
                    body: CircularProgressIndicator(color: Colors.red),
                  );
                }
                
                if (snap.hasError || !snap.data!) {
                  print("用户注册失败: ${snap.error}");
                  return const AuthScreen();
                }
                
                print("user registered? ${snap.data}");
                return const Gaide();
              }),
            );
          }
          
          print("Show AuthScreen");
          return const AuthScreen();
        },
      ),
    );
  }
}

3. 处理audio_service引发的进程重复启动

如果使用audio_service,调整Android端配置避免主进程重复初始化:

  • 在AndroidManifest.xml的service标签中添加android:stopWithTask="true"(按需调整)
  • 在AudioService的onStartCommand方法中返回START_NOT_STICKY,避免系统重启进程后重复执行初始化

额外建议

  • 启用Firebase Crashlytics捕获崩溃堆栈,精准定位冻结/崩溃的具体原因
  • Release模式下关闭DebugPrint,减少日志对性能的影响
  • 使用flutter build apk --release生成安装包测试,排除调试环境干扰

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 06:33:19