Flutter桌面应用登录状态切换报错:Bad state: Stream has already been listened to
Flutter桌面应用firedart登录状态监听重复报错解决
问题描述
开发基于Firebase的Flutter桌面应用,使用firedart包实现登录逻辑,登录功能正常,但根据登录状态自动切换页面时,每次重新加载FirstPage都会触发错误:Bad state: Stream has already been listened to。
问题原因
firedart的FirebaseAuth.instance.signInState是单订阅流,这种流只能被监听一次。当前代码中MyHomePage的build方法每次重建都会创建新的StreamBuilder并监听该流,导致重复订阅触发错误。
解决方案
将单订阅流转换为多订阅流(Broadcast Stream),允许多次监听。在State的initState中初始化广播流,确保只转换一次,避免重复操作。
修改后的main.dart代码
import 'package:ame/screens/firstPage.dart'; import 'package:ame/screens/loginPage.dart'; import 'package:bitsdojo_window/bitsdojo_window.dart'; import 'package:firedart/auth/firebase_auth.dart'; import 'package:firedart/auth/token_store.dart'; import 'package:firedart/firestore/firestore.dart'; import 'package:flutter/material.dart'; import 'package:flutter_acrylic/flutter_acrylic.dart'; import 'package:google_fonts/google_fonts.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Window.initialize(); await Window.setEffect( effect: WindowEffect.aero, color: const Color.fromARGB(50, 0, 0, 0), ); FirebaseAuth.initialize( "AIzaSyBk76lyEHpyDgMot7csMmDiIKnPS_5QiYE", VolatileStore()); var auth = FirebaseAuth.instance; runApp(const MyApp()); doWhenWindowReady(() { var initialSize = const Size(600, 450); appWindow.minSize = initialSize; }); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Demo', theme: ThemeData( fontFamily: GoogleFonts.poppins().fontFamily, colorScheme: ColorScheme.fromSwatch().copyWith( primary: const Color.fromRGBO(7, 96, 49, 1), secondary: Colors.white, ), ), routes: { '/firstPage': (ctx) => const FirstPage(), '/loginPage': (ctx) => const LoginPage(), }, home: const MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key}) : super(key: key); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { late Stream<bool> _authStream; @override void initState() { super.initState(); // 转换为多订阅流,支持多次监听 _authStream = FirebaseAuth.instance.signInState.asBroadcastStream(); } @override Widget build(BuildContext context) { return StreamBuilder( stream: _authStream, builder: (context, snapshot) { if (snapshot.hasData && snapshot.data == true) { return const FirstPage(); } else { return const LoginPage(); } }); } }
补充说明
asBroadcastStream()包装后的流可以被多个订阅者同时监听,不会触发重复监听错误- 也可以全局初始化这个广播流,在整个应用中复用,避免重复转换
- 使用
StreamBuilder时无需手动管理订阅生命周期,框架会自动处理
内容的提问来源于stack exchange,提问作者Chirag Maurya
相关产品推荐
相关产品推荐

