0

what I am trying to do is check if user is logged in already or not. there is a futurebuilder inside consumer which is notifying listeners. check code:

@override
Widget build(BuildContext context) {
return MultiProvider(
  providers: [
    ChangeNotifierProvider.value(
      value: Auth(),
    )
  ],
  child: Consumer<Auth>(
    builder: (ctx, auth, _) {
      print('making it again and again');
      return MaterialApp(
          title: 'MY app',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            accentColor: Colors.deepOrange,
          ),
          home: auth.isAuth
              ? FirstScreen()
              : FutureBuilder(
                  future: auth.tryAutoLogin(), //inside this function there is notifylisteners()
                  builder: (ctx, authResultSnapShot) =>
                      authResultSnapShot.connectionState ==
                              ConnectionState.waiting
                          ? SplashScreen()
                          : AuthScreen(),
                ));
    },
  ),
);

}

What I get:

this is rebuilding the app again and again. tryautologin is called repeatedly.

What I want:

check for is a user logged in only once the app is started.

Future<bool> tryAutoLogin() async {
  final prefs = await SharedPreferences.getInstance();
  if (!prefs.containsKey('userData')) {
    return false;
  }
  final extractedUserData = json.decode(prefs.getString('userData'));
  final expiryDate = DateTime.parse(extractedUserData['expiryDate']);
  _accessToken = extractedUserData['accessToken'];
  _refreshToken = extractedUserData['refreshToken'];
  print(extractedUserData['userId']);
  _userId = extractedUserData['userId'];
  if (expiryDate.isBefore(DateTime.now())) { //for now this if statement is not running
    try {
      await _getAccessToken();
    } catch (error) {
      return false;
    }
  }
  print('tryautologin');
  notifyListeners();
  _autoGetAccessToken(); //this function doesn't have any notifylisteners
  return true;
}

edited:

String get accessToken {
  if (_expiryDate != null &&
    _expiryDate.isAfter(DateTime.now()) &&
    _accessToken != null) {
      return _accessToken;
  }
  return null;
}

bool get isAuth {
  print(accessToken != null);
  return accessToken != null;
}
Sumit Yadav
  • 97
  • 1
  • 11
  • See https://stackoverflow.com/questions/52249578/how-to-deal-with-unwanted-widget-build – Rémi Rousselet Jan 17 '20 at 21:00
  • Is `isAuth` always returning false? So `auth.tryAutoLogin()` calls `notifyListeners` and the consumer is rebuilt, calling `isAuth` again and again? How does your `tryAutoLogin()` method look like? – Frank Treacy Jan 17 '20 at 22:32
  • @FrankTreacy edited the question. mayebe consumer is rebuild than futurebuilder calling tryautologin() which has notifylisteners() again consumer is rebuilt and this goes on forever. – Sumit Yadav Jan 18 '20 at 08:25
  • @FrankTreacy at app start isAuth returning false. after tryautologin which is setting accesstoken than it is returning true – Sumit Yadav Jan 18 '20 at 08:29
  • @FrankTreacy thanx for the help isAuth was returning false every time. I was not setting _expiryDate so it was affecting isAuth. you can answer this question. – Sumit Yadav Jan 18 '20 at 09:02

1 Answers1

0

Even the question is old quite a bit of time, this answer will help another. I have faced the problem also. this happens when you use a future builder inside a consumer. it is rebuilding again and again infinitely. So, instead of the future builder try using an if-else statement.

child: Consumer<Auth>(
    builder: (ctx, auth, _) {
      //Sizedbox() used for nullsafety
      Widget child = SizedBox();
      if (auth.isAuth) {
        child = FirstScreen();
      } else if (!auth.triedAutoLogin) {
        auth.tryAutoLogin();
        child = SplashScreen();
      } else {
        child = AuthScreen();
      }
      return MaterialApp(
        title: 'MY app',
        theme: ThemeData(
          primarySwatch: Colors.blue,
          accentColor: Colors.deepOrange,
        ),
        home: child,
      );
    },
  ),

inside Auth class keep a boolean variable like triedAutoLogin to keep track.

Madupoorna
  • 575
  • 4
  • 5