简体   繁体   中英

Flutter/FirebaseAuth : How can I autologin a user at app launch?

I have the following methods to see if the user is already logged in, which in this case I did log in and the getCurrentUser() function works because in the console it does return "USER IS NOT NULL" but the home widget is still null giving me the "EXCEPTION CAUGHT BY WIDGETS LIBRARY" saying that the home can't be null and stuff.

userAPI.dart

Future<FirebaseUser> getCurrentUser() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();

if (user != null) {
  return user;
} else {
  return null;
}
}

main.dart

class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
Widget home;

APIs().usersAPI.getCurrentUser().then((u) {
  if (u == null) {
    print('USER IS NULL');
    home = WelcomePage();
  } else {
    print('USER IS NOT NULL');
    home = FeedPage();
  }
});

return MaterialApp(
  title: "Jedi",
  debugShowCheckedModeBanner: false,
  home: home,
  routes: {
    '/login' : (context) => new LoginPage(),
    '/feed' : (context) => new FeedPage(),
  },
);
}
}

You need to make the App a StatefulWidget and call setState when setting the home page

setState(() {
   home = WelcomePage();
});

setState(() {
   home = FeedPage();
});

Plus you may need to set the home page to something other than null before the API returns.

What probably would be a better pattern is to use a FutureBuilder . This way you will be returning the correct Widget depending on the state you are in.

return MaterialApp(
  title: "Jedi",
  debugShowCheckedModeBanner: false,
  home: FutureBuilder<FirebaseUser>(
     future: APIs().usersAPI.getCurrentUser(),
     builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {

        switch (snapshot.connectionState) {
            case ConnectionState.none:
            case ConnectionState.waiting: 
               return CircularProgressIndicator();
            default: 
               if (snapshot.hasError)
                  return Text('Error: ${snapshot.error}');
               else
                 if(snapshot.data == null)
                    return WelcomePage();
                 else 
                    return FeedPage();
        }

     }
  ),
  routes: {
    '/login' : (context) => new LoginPage(),
    '/feed' : (context) => new FeedPage(),
  },
);
}

Advancing the answer given by @aqwert, you need to check for the user is not null/is null after the connection status. See below working example - this assumes autologin if user is not null.

class LandingPage extends StatelessWidget {//call this class from the main.dart
 @override
 Widget build(BuildContext context) {
  return StreamBuilder<FirebaseUser>(
  stream: FirebaseAuth.instance.onAuthStateChanged,
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.active) {
      FirebaseUser user = snapshot.data;//get the user status once the connection is established
      if (user == null) {
        //print("User is NULL::: " + user.toString());
        return LoginScreen();//
      }
      print("User is NOT NULL::: " + user.toString());
      return DefaultScreen();//home screen
    } else {
      return Scaffold(
        body: Center(
          child: CircularProgressIndicator(),//called in case all fails while waiting for connection status
        ),
      );
    }
  },
);

Here is my simple solution you can try this, First we need a stateful widget and override the function initState() inside initState() we can work something look like this-

class _MyAppState extends State<MyApp> {
  String initPage;
  final FirebaseAuth auth=FirebaseAuth.instance;
  User currentUser;

  @override
  void initState() {
    super.initState();
    try {
      currentUser = auth.currentUser;
      if(currentUser!=null){
        initPage=Chat.id;
 /*
      here id is static variable which declare as a page name.
       */
      }
      else{
        initPage=Home.id;
      }
    }
    catch(e){
      print(e);
      initPage=Home.id;
    }

  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
 

      initialRoute: initPage,
      routes: {
        Home.id: (context) => Home(),
        Login.id: (context) => Login(),
        Registration.id: (context) => Registration(),
        Chat.id: (context) => Chat(),
      },
    );
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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