简体   繁体   English

无法在 flutter 中使用提供程序来处理身份验证流程

[英]Not able to use provider in flutter for handling Authentication flow

If anyone is not able to understand my problem please inform如果有人无法理解我的问题,请告知

I have used Provider package to handle authentication flow.我已经使用 Provider package 来处理身份验证流程。 What I am doing is: Main.dart -> Auth handler widget(Which contain stream builder to check the onAuthChange) -> Page Handler(Here if the user is new it will take the user to onboarding screen from there it is transferred to Login page using push replacement) After login it is taken to check user if the data exist or not -> if exist it is taken to home screen -> Home screen contains 3 tab.我正在做的是: Main.dart -> Auth 处理程序小部件(其中包含 stream 构建器以检查 onAuthChange) -> 页面处理程序(这里如果用户是新用户,它将把用户带到登录屏幕从那里转移到登录使用推送替换的页面)登录后检查用户是否存在数据 -> 如果存在,则将其带到主屏幕 -> 主屏幕包含 3 个选项卡。 In home tab there is signOut button, but when I press it doesn't work.在主页选项卡中有注销按钮,但是当我按下它时它不起作用。 Help me in this.在这方面帮助我。

Main.dart主.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 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 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(),
      ),
    );
  }
}

In checkUser.dart if data exist在 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 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),
            ),
          ),
        ],
      ),
    );
  }
}

In Hometab the signOut button function在 Hometab 中,signOut 按钮 function

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

This may help you.这可能会对您有所帮助。 I'm not sure but this works for me我不确定,但这对我有用

Signout Fuction登出功能

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

Function Usage Function 用途

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

You need to have AuthWidgetBuilder as top-level widget (ideally above MaterialApp) so that the entire widget tree is rebuilt on sign-in / sign-out events.您需要将 AuthWidgetBuilder 作为顶级小部件(最好在 MaterialApp 之上),以便在登录/注销事件时重建整个小部件树。

You could make SplashScreen a child, and have some conditional logic to decide if you should present it.你可以让 SplashScreen 成为一个孩子,并有一些条件逻辑来决定你是否应该展示它。

By the way, if your splash screen doesn't contain any animations you don't need a widget at all, and you can use the Launch Screen on iOS or equivalent on Android (there's tutorials about this online).顺便说一句,如果您的初始屏幕不包含任何动画,则您根本不需要小部件,您可以使用 iOS 上的启动屏幕或 Android 上的等价物(网上有关于此的教程)。 By @bizz84通过@bizz84

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM