If anyone is not able to understand my problem please inform
I have used Provider package to handle authentication flow. 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. In home tab there is signOut button, but when I press it doesn't work. Help me in this.
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(),
),
);
}
}
In checkUser.dart if data exist
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),
),
),
],
),
);
}
}
In Hometab the signOut button function
Future<void> _signOut(BuildContext context) async {
try {
final auth = Provider.of<AuthBase>(context, listen: false);
await auth.signOut();
} catch (e) {
print(e);
}
}
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.
You could make SplashScreen a child, and have some conditional logic to decide if you should present it.
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). By @bizz84