Reputation: 23
This is the middle part of the main that is expected to cause the error. If you are not logged in on the splash screen, this code goes to MyHomePage and logs in. If you are logged in, it goes to MainScreen and switches to the main screen of the app.
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
final FirebaseAuth auth = FirebaseAuth.instance;
final User? user = FirebaseAuth.instance.currentUser;
@override
void initState() {
super.initState();
_initUser().whenComplete((){
setState(() {});
});
}
_initUser() async {
if (auth.currentUser != null) {
Timer(
Duration(seconds: 2),
() => Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) =>
MainScreen(user!)),
(Route<dynamic> route) => false),
);
} else {
Timer(Duration(seconds: 1),
() => Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) =>
MyHomePage()),
(Route<dynamic> route) => false),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text("Splash Screen"),
),
);
}
}
This is the MyHomePage widget that is passed when you are not logged in.
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: TextButton(
onPressed: (){
FirebaseService().signup(context);
},
child: Text('Google'),
),
)
);
}
}
class FirebaseService{
final FirebaseAuth auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
Future<void> signup(BuildContext context) async {
final GoogleSignInAccount? googleSignInAccount = await googleSignIn.signIn();
if (googleSignInAccount != null) {
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;
final AuthCredential authCredential = GoogleAuthProvider.credential(
idToken: googleSignInAuthentication.idToken,
accessToken: googleSignInAuthentication.accessToken);
// Getting users credential
UserCredential result = await auth.signInWithCredential(authCredential);
User? user = result.user;
if (user != null) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => MainScreen(user)));
} // if result not null we simply call the MaterialpageRoute,
// for go to the HomePage screen
}
}
Future<void> signOutFromGoogle() async{
await googleSignIn.signOut();
await auth.signOut();
}
}
This is the content of the error
The following LateError was thrown building MainScreen(dirty, dependencies: [_InheritedProviderScope<Pro?>], state: _MainScreenState#d95a0):
LateInitializationError: Field '_instance@640075166' has not been initialized.
The relevant error-causing widget was:
MainScreen MainScreen:file:///F:/flutter%20project/good_man/lib/main.dart:75:25
When the exception was thrown, this was the stack:
Sorry, I forgot the mainscreen code. Below is the mainscreen code
class MainScreen extends StatefulWidget {
const MainScreen(this.user);
final User user;
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
@override
Widget build(BuildContext context) {
final User user = widget.user;
final pro = Provider.of<Pro>(context);
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(60.0), // here the desired height
child: AppBar(
iconTheme: IconThemeData(color: Colors.black),
backgroundColor: pro.backColor_main,
elevation: 0.0,
centerTitle: true,
title: Text('aaa',
style: TextStyle(
fontFamily: 'Gugi',
fontSize: 20.sp,
color: Colors.black,
),),
),
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
DrawerHeader(
child: Text('Drawer Header'),
decoration: BoxDecoration(
color: Colors.white
),
),
ListTile(
title: Text('aaa'),
onTap: () {
Navigator.pop(context);
},
),
],
),
),
bottomNavigationBar: BottomBar(),
body: Stack(children: [
TabBarView(
children: [
MainTest(),
Text(''),
Main_User(user),
],
),
])),
);
}
}
Sorry for posting all the code. There is no part that uses late , but the error code is displayed as late, and I try to delete the caches and start
Upvotes: 2
Views: 16091
Reputation: 219
Don't initialise the async task into the initState
. Because of Flutter Life Cycle it can not await the flow...
For more about the lIfe Cycle please visit this:
Life Cycle of Widget
So Solution is... Use the FutureBuilder for awaiting the widget....
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
final FirebaseAuth auth = FirebaseAuth.instance;
final User? user = FirebaseAuth.instance.currentUser;
_initUser() async {
if (auth.currentUser != null) {
Timer(
Duration(seconds: 2),
() => Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) =>
MainScreen(user!)),
(Route<dynamic> route) => false),
);
} else {
Timer(Duration(seconds: 1),
() => Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) =>
MyHomePage() ),
(Route<dynamic> route) => false),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _initUser(),
builder: (context, snapshot) {
if(snapshot.hasData){
//You you finish the initialization
return Text("You Get the Data");
}
//Until the data get
return Center(child: Text("Splash Screen"),);
},
),
);
}
}
Upvotes: 2
Reputation: 2137
Actually error is in Initialisation of current user... You have to understand Life cycle of stateful widget... initState is not holding flow. it just initialise some some instance value...And you try to delay for 2 sec... So that's the issue.
Use FutureBuilder for _initUser()
and when it fetch all data then proceed for the next screen.
Upvotes: 3