【问题标题】:Not able to use provider in flutter for handling Authentication flow无法在颤振中使用提供者来处理身份验证流程
【发布时间】:2020-11-05 19:37:11
【问题描述】:

如果有人无法理解我的问题,请告知

我已使用 Provider 包来处理身份验证流程。 我正在做的是: Main.dart -> Auth 处理程序小部件(其中包含用于检查 onAuthChange 的流构建器) -> 页面处理程序(如果用户是新用户,它将带用户从那里进入登录屏幕,它被转移到登录使用推送替换的页面)登录后检查用户是否存在数据 -> 如果存在,则将其带到主屏幕 -> 主屏幕包含 3 个选项卡。在主页选项卡中有注销按钮,但是当我按下它时它不起作用。帮帮我。

Main.dart

Provider<AuthBase>(
      create: (context)=>Auth(),
      child: MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Rapport',
          theme: ThemeData(
            primaryColor: Color(0xFFE3F2FD),
            visualDensity: VisualDensity.adaptivePlatformDensity,
            pageTransitionsTheme: PageTransitionsTheme(
              builders: {
                TargetPlatform.android: CustomPageTransitionsBuilder(),
                TargetPlatform.iOS: CustomPageTransitionsBuilder(),
              },
            ),
          ),

          /*This is the routes table. Add all the route names used inside the app here
        Add the route name where the route is made as static const String, so as to you don't need to remember anything.
         */
          routes: {
            //the route name / stands for home / first route in the app.
            '/': (ctx) {
              return SplashScreen.navigate(
                name: 'assets/splash.flr',
                next: (context) {
                  print(isLogin.toString());
                  return AuthWidgetBuilder(dataExists: myData.length==0,isLogin: isLogin,builder: (context, userSnapshot,isLogin,dataExist) {
                    return Scaffold(
                      body: AuthWidget(userSnapshot: userSnapshot,dataExists: myData.length==0,isLogin: isLogin,),
                    );
                  });
                },
                startAnimation: 'Untitled',
                until: () => Future.delayed(Duration(seconds: 4)),
                backgroundColor: Colors.white,
              );
            },
            LoginScreen.loginRoute: (ctx) => LoginScreen(),
            CheckUser.checkRoute: (ctx) => CheckUser(),
            OnboardingScreen.onBoardRoute: (ctx) => OnboardingScreen(),
            StudentInfo.studentRoute: (ctx) => StudentInfo(),
            PersonalDetails.routeName:(ctx) => PersonalDetails(),
            ProfessionalDetails.routeName:(ctx) => ProfessionalDetails(),
            AddressDetails.routeName: (ctx) => AddressDetails(),
            TeacherHomeScreen.routeName:(ctx)=>TeacherHomeScreen(),
            TeacherVerification.routeName:(ctx)=>TeacherVerification(),
            StudentHomeScreen.routeName : (ctx)=>StudentHomeScreen(),
          },
        ),
    );

Auth_Widget_Builder

class AuthWidgetBuilder extends StatelessWidget {
  const AuthWidgetBuilder({Key key, @required this.builder,@required this.isLogin,@required this.dataExists}) : super(key: key);
  final Widget Function(BuildContext, AsyncSnapshot<User>,String,bool) builder;
  final String isLogin;
  final bool dataExists;


  @override
  Widget build(BuildContext context) {
    print('AuthWidgetBuilder rebuild');
    print(dataExists);
    final authService =
    Provider.of<AuthBase>(context, listen: false);
    return StreamBuilder<User>(
      stream: authService.onAuthStateChanged,
      builder: (context, snapshot) {
        print('StreamBuilder: ${snapshot.connectionState}');
        final User user = snapshot.data;
        if (user != null) {
          SharedPrefFunction().saveLoginPreference();
          return MultiProvider(
            providers: [
              Provider<User>.value(value: user),
            ],
            child: builder(context, snapshot,'true',dataExists),
          );
        }
        return builder(context, snapshot,isLogin,dataExists);
      },
    );
  }
}

Auth.Widget

class AuthWidget extends StatelessWidget {
  const AuthWidget({Key key, @required this.userSnapshot,this.dataExists,this.isLogin}) : super(key: key);
  final AsyncSnapshot<User> userSnapshot;
  final String isLogin;
  final bool dataExists;

  @override
  Widget build(BuildContext context) {
    if (userSnapshot.connectionState == ConnectionState.active) {
      if(isLogin == null){
        return OnboardingScreen();
      }
      else{
        return userSnapshot.hasData ? CheckUser(dataExist: dataExists,) : LoginScreen();
      }
    }
    return Scaffold(
      body: Center(
        child: CircularProgressIndicator(),
      ),
    );
  }
}

如果数据存在,则在 checkUser.dart 中

homePage(BuildContext context) {
    print('checkUser');
    if (dataExists) {
      return Scaffold(
        body: SafeArea(
          child: Container(
            child: Column(
              children: <Widget>[
                Text(
                  'Welcome',
                  style: kTextStyle,
                ),
                FlatButton.icon(
                  onPressed: () {
                    setState(() {
                      Navigator.of(context).pushReplacementNamed(
                        StudentHomeScreen.routeName,   //This line is changed by me. This code is not correct and needs to be changed.
                      );
                    });
                  },
                  icon: Icon(Icons.home),
                  label: Text('Home'),
                ),
              ],
            ),
          ),
        ),
      );
    } else {
      return getInfoPage();
    }
  }

Student_Home_Screen.dart

class _StudentHomeState extends State<StudentHomeScreen> {
  bool _isProfilePicSet = false;
  int _currentTabIndex = 1;
  var _tabs = [
    Center(
      child: Text('Search Tab'),
    ),
    HomeTab(),
    Center(
      child: Text('Profile Tab'),
    ),
  ];

  @override
  Widget build(BuildContext context) {
    var size = MediaQuery.of(context).size;
    return Scaffold(
      backgroundColor: Colors.white,
      body: _tabs[_currentTabIndex],
      bottomNavigationBar: BottomNavigationBar(
//        type: BottomNavigationBarType.shifting,
        backgroundColor: Colors.white,
//        fixedColor: Colors.black,
        iconSize: 24,
        selectedIconTheme: IconThemeData(
          color: themeColor,
          opacity: 1,
        ),
        unselectedIconTheme: IconThemeData(
          color: themeColor,
          opacity: 0.6,
        ),
        showUnselectedLabels: false,
        showSelectedLabels: true,
        elevation: 10,
        currentIndex: _currentTabIndex,
        onTap: (index) {
          setState(() {
            _currentTabIndex = index;
          });
        },
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            title: Text(
              'Search',
              style: subhead2.copyWith(color: themeColor),
            ),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text(
              'Home',
              style: subhead2.copyWith(color: themeColor),
            ),
          ),
          BottomNavigationBarItem(
            icon: CircleAvatar(
              backgroundImage: _isProfilePicSet
                  ? NetworkImage('set link here')
                  : AssetImage('assets/images/default.png'),
              maxRadius: 12,
            ),
            title: Text(
              'Profile',
              style: subhead2.copyWith(color: themeColor),
            ),
          ),
        ],
      ),
    );
  }
}

Hometab 中的退出按钮功能

  Future<void> _signOut(BuildContext context) async {
    try {
      final auth = Provider.of<AuthBase>(context, listen: false);
      await auth.signOut();
    } catch (e) {
      print(e);
    }
  }

【问题讨论】:

  • 您实际上遇到了什么错误?是 Provider not found 错误还是类似的错误?检查错误日志应该始终是第一步。
  • 我没有收到任何错误。我已将 AuthBase 提供程序放在顶部,以便我可以从任何页面注销,但它没有发生。我不知道为什么会这样。
  • 感谢@bizz84 帮助我。我已经在下面发布了你的答案

标签: flutter flutter-provider state-management flutter-state


【解决方案1】:

这可能会对您有所帮助。我不确定,但这对我有用

注销功能

Future _signOut() async {
    try {
      return await auth.signOut();
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

函数用法

IconButton(
  onPressed: () async {
    await _auth.signOut();
    MaterialPageRoute(
      builder: (context) => Login(),
    );
  },
  icon: Icon(Icons.exit_to_app),
),

【讨论】:

    【解决方案2】:

    您需要将 AuthWidgetBuilder 作为顶级小部件(最好在 MaterialApp 之上),以便在登录/注销事件时重建整个小部件树。

    你可以让 SplashScreen 成为一个孩子,并有一些条件逻辑来决定你是否应该展示它。

    顺便说一句,如果您的初始屏幕不包含任何动画,则您根本不需要小部件,您可以在 iOS 上使用 Launch Screen 或在 Android 上使用同等功能(网上有关于此的教程)。 作者@bizz84

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-25
      • 1970-01-01
      • 1970-01-01
      • 2021-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多