Flutter入门:点击按钮后StreamBuilder无法重建UserSettingsPage问题
问题:StreamBuilder无法重建UserSettingsPage组件
我的组件树中,StreamBuilder(紫色) 负责根据Firebase auth状态切换页面,点击FloatingActionButton(红色) 触发登出操作后,应用会重建,但UserSettingsPage(绿色) 不在StreamBuilder的下级组件树中,因此不会被重建,我需要让它能随auth状态变化更新或重建。
我的初步思路:
- 将StreamBuilder移到MaterialApp上方,但不知道具体实现方式
- 将UserSettingsPage移到HomePage同级
解决方案
方案1:在UserSettingsPage中直接监听auth状态变化
通过监听FirebaseAuth的authStateChanges流,当用户登出时自动跳转到登录页,同时实时更新页面UI。
修改UserSettingsPage代码:
class UserSettingsPage extends StatefulWidget { const UserSettingsPage({Key? key}) : super(key: key); @override _UserSettingsPageState createState() => _UserSettingsPageState(); } class _UserSettingsPageState extends State<UserSettingsPage> { late StreamSubscription<User?> _authSubscription; @override void initState() { super.initState(); // 监听auth状态变化 _authSubscription = FirebaseAuth.instance.authStateChanges().listen((user) { if (user == null) { // 登出后清空导航栈,跳转到登录页 Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (context) => const LoginPage()), (route) => false, ); } }); } @override void dispose() { _authSubscription.cancel(); super.dispose(); } @override Widget build(BuildContext context) { final provider = Provider.of<GoogleSignInProvider>(context); return Scaffold( body: ListView( children: [ Text('登录状态:${provider.isLoggedWithGoogle() ? '已登录' : '已登出'}'), ElevatedButton( onPressed: () { final provider = Provider.of<GoogleSignInProvider>(context, listen: false); provider.logout(); }, child: const Text('退出登录'), ), ], ), ); } }
方案2:将StreamBuilder提升到MaterialApp外层
把StreamBuilder放在MaterialApp的外层,让整个应用都能响应auth状态变化,登出后直接切换到登录页。
修改main.dart代码:
void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => GoogleSignInProvider()), ChangeNotifierProvider(create: (_) => ThemesProvider()), ChangeNotifierProvider(create: (_) => ZmienneClass()) ], child: const MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return StreamBuilder<User?>( stream: FirebaseAuth.instance.authStateChanges(), builder: (context, snapshot) { return MaterialApp( debugShowCheckedModeBanner: false, theme: Provider.of<ThemesProvider>(context).darkModeOn ? ThemeOptions.white : ThemeOptions.black, home: Scaffold( body: _buildAuthContent(snapshot), ), ); }, ); } Widget _buildAuthContent(AsyncSnapshot<User?> snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasData) { return const HomePage(); } else if (snapshot.hasError) { return const Center(child: Text("出现错误..")); } else { return const LoginPage(); } } }
额外修复:GoogleSignInProvider中的无效代码
原代码中logout方法里的isLoggedWithGoogle() == false;是无效语句,删除后修正:
class GoogleSignInProvider extends ChangeNotifier { bool isLoggedWithGoogle() { final provUser = FirebaseAuth.instance.currentUser; return provUser?.providerData[0].providerId == "google.com"; } Future logout() async { final provUser = FirebaseAuth.instance.currentUser; if (provUser != null && provUser.providerData[0].providerId == "google.com") { await googleSignIn.disconnect(); } await FirebaseAuth.instance.signOut(); notifyListeners(); } }
内容的提问来源于stack exchange,提问作者Malak
相关产品推荐
相关产品推荐

