如何基于riverpods streamProvider更新嵌套屏幕?

问题描述

假设有三个屏幕。 main.dart、home.dart 和 signIn.dart 我有代码,如下所示。当我在主屏幕并且 streamProvider(firebaseAuthStateProvider) 更改时,我将自动返回到 main.dart 屏幕。之后,if-query 将我直接发送到 signIn.dart 屏幕。就像预期的那样。但是,当我创建一个新的嵌套屏幕并且 streamProvider 更改其值时,“根”屏幕 (home.dart) 不会将我发送回登录屏幕。所以我想它只适用于第一个孩子而不是嵌套的孩子。

是否可以只用一个查询来检查根屏幕中的 streamProvider,还是我必须在每个屏幕中都放置一个查询来检查值?

class SignInCheck extends ConsumerWidget {
  @override
  Widget build(BuildContext context,ScopedReader scopedReader) {
    final _authState = scopedReader(firebaseAuthStateProvider); //
    return _authState.when(data: (value) {
      if (value != null) {
        return HomeScreen();
      } else {
        return SignIn();
      }
      //...

解决方法

只要最高的widget是监听auth状态变化的那个,所有的孩子都会受到屏幕变化的影响。下面的代码是我不久前在 GitHub 上找到的,并且一直是我所有 Flutter 项目的首选。

AuthHome() 是我的顶级小部件,它是我应用程序其余部分的父级

auth_home.dart:

class AuthHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AuthWidget(
          signedInBuilder: (context) => NavBase(),signedOutBuilder: (context) => Login());
  }
}

auth_widget.dart:

class AuthWidget extends ConsumerWidget {
  AuthWidget(
      {required this.signedInBuilder,required this.signedOutBuilder});
  final WidgetBuilder signedInBuilder;
  final WidgetBuilder signedOutBuilder;
  

  @override
  Widget build(BuildContext context,watch) {
    final authStateChanges = watch(authStateChangesProvider);
    return authStateChanges.when(
      data: (user) => _data(context,user),loading: () => const Scaffold(
        body: Center(
          child: CircularProgressIndicator(),),error: (err,__) {
        print(err);
        return Scaffold(
          body: EmptyContent(
            title: 'Something went wrong',message: 'Can\'t load data right now.',);
      },);
  }

  Widget _data(BuildContext context,User? user) {
    if (user != null) {
      return signedInBuilder(context);
    }
    return signedOutBuilder(context);
  }
}

其中 NavBase() 是应用的其余已验证部分所在的位置