Flutter how to redirect to login if not authorized

Code should have single resonpsibility. Your getPost method are doing 2 things at the same time. You should break this function such that it either successfully get the the post, or throw exception, and its caller will handle the exception. Its caller btw must be within build method, because only build method has BuildContext context, something like this:

      if (response.body.toString().contains('Token is Expired')) {
        throw new Exception("Token is Expired") // you may want to implement different exception class
      }
      body: new Container(
        padding: new EdgeInsets.only(bottom: 8.0),
        color: Color(0xff2c3e4e),
        child: FutureBuilder<List<Post>>(
            future: api.getposts(),
            builder: (context, snapshot) {
              if (snapshot.hasError) {
                // you might want to handle different exception, such as token expires, no network, server down, etc.
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => LoginScreen()),
                );
                return Container(); // return empty widget
              }
              if (snapshot.hasData) {
                // do somthing with data
                return Text('Some data here');
              }
              // has no data
              return Text("Loading...");

            }),
      ),

UPDATE

Thanks to @TruongSinh I got it figured out.

Followed his example and figured out the build navigator method which works:

if (snapshot.hasError) {

              @override
              void run() {
                scheduleMicrotask(() {

                  Navigator.pushReplacement(
                    context,
                    MaterialPageRoute(builder: (context) => LoginScreen()),
                  );
                });
              }
              run();
}

Update: added a package containing several guards like this

I did it with a StreamBuilder to react on change and be able to display a SplashScreen when we don't know yet if the user is connected.

StreamBuilder authGuard = StreamBuilder(
  stream: Auth.authState$,
  builder: (context, snapshot) {
    switch (snapshot.data) {
      case AuthState.PENDING:
        return SplashScreen();
      case AuthState.UNAUTHENTICATED:
        return SignInScreen();
      case AuthState.AUTHENTICATED:
        return HomeScreen();
      default:
        return SplashScreen();
    }
  },
);

So it will change screen depending on the AuthState:

return MaterialApp(
  // ...
  home: authGuard,
);

And my auth class

import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:rxdart/rxdart.dart';

enum AuthState { PENDING, AUTHENTICATED, UNAUTHENTICATED }

class Auth {
  static final FirebaseAuth _auth = FirebaseAuth.instance;
  static final GoogleSignIn _googleSignIn = GoogleSignIn();

  static Stream<AuthState> authState$ = FirebaseAuth.instance.onAuthStateChanged
      .map((state) =>
          state != null ? AuthState.AUTHENTICATED : AuthState.UNAUTHENTICATED)
      .startWith(AuthState.PENDING);

  static Future<FirebaseUser> signInWithGoogle() async {
    // ...
  }
}

Tags:

Flutter