16

I want to judge which page to start up in main (actually is login page and the home page). So I have to read isLogin in preferences. How to do that in main?

I tied these codes:

Future<Null> checkIsLogin() async {
  String _token = "";
  // If token exist already, then HomePage
  SharedPreferences prefs = await SharedPreferences.getInstance();
  _token = prefs.getString("token");
  print('get token from prefs: ' +  _token);
  if (_token != "" && _token != null) {
    // already login
    print("alreay login.");
    isLogin = true;
  }
}

void main() {
  App.init();
  // if we have token then go to HomePage directly otherwise go to LoginPage.
  Widget _defaultHome = new LoginPage();
  checkIsLogin();
  if (isLogin) {
    _defaultHome = new HomePage();
  }

  runApp(new MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: globalThemeData,
      home: _defaultHome
  ));
}

above code, isLogin is an global variable. There was an error:

Performing full restart...                                       
Restarted app in 2,810ms.
[VERBOSE-2:dart_error.cc(16)] Unhandled exception:
Invalid argument(s)
#0      _StringBase.+ (dart:core/runtime/libstring_patch.dart:245:57)
#1      checkIsLogin (file:///Volumes/xs/awesome/uranus/clients/flutter/flutter_asgard/lib/main.dart:17:34)
<asynchronous suspension>
#2      main (file:///Volumes/xs/awesome/uranus/clients/flutter/flutter_asgard/lib/main.dart:29:3)
#3      _startIsolate.<anonymous closure> (dart:isolate/runtime/libisolate_patch.dart:279:19)
#4      _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:165:12)

Seems there are issue to call async in main, how to get it to work?

Nicholas Jela
  • 2,540
  • 7
  • 24
  • 40

5 Answers5

14

This is what i did,

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SharedPreferences.getInstance().then((instance) {
    StorageService().sharedPreferencesInstance = instance; // Storage service is a service to manage all shared preferences stuff. I keep the instance there and access it whenever i wanted.
    runApp(MyApp());
  });
}

Then in the Material App Build

@override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'App Title',
      home: _checkUserLoggedIn()
          ? HomeScreen()
          : LoginPage(),
    );
  }

_checkUserLoggedIn Function

bool _checkUserLoggedIn() {
    return _storageService.getFromShared('isLoggedIn'); //  Just a get method from shared preferences
}
Kavinda Jayakody
  • 705
  • 1
  • 13
  • 25
  • Probably the OP is talking about this SharedPreferences plugin : https://pub.dev/packages/shared_preferences. 1) Where do you find the `.then((instance) {` part in the plugin documentation ? 2) inside `_checkUserLoggedIn()` function , where do you get the `storageService` variable ? – Istiaque Ahmed Mar 26 '20 at 20:09
  • @IstiaqueAhmed hey man, sorry for the long delay, Just saw the comment now 1) It's already there mate, no need to search. In the official documentation it says to use "await SharedPreferences.getInstance()" to get the instance. Using await means it's a promise -> which we can also use as .then((instance)) (as in the async way). 2) I used _storageService here as just a placeholder and how i handled dependencies in my app (my way :D). It's just a singleton service which i used to abstract the work of the storage service implemented through SharedPreferences – Kavinda Jayakody Apr 28 '20 at 19:10
5

You need await checkIsLogin.

This is my code:

Future<Null> main() async {
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeRight,
    DeviceOrientation.landscapeLeft,
  ]);
  Screen.keepOn(true);
  SharedService.sharedPreferences = await SharedPreferences.getInstance();
  account = SharedService.sharedPreferences.getString("Account");
  password = SharedService.sharedPreferences.getString("Password");
  runApp(new MyApp());
}
蔡旻袁
  • 171
  • 1
  • 1
  • 7
  • 1
    If you getting some exception relating to `ServiceBinding` then just call `WidgetsFlutterBinding.ensureInitialized();` as the initial line of your main function. CHeck this: https://stackoverflow.com/questions/57689492/flutter-unhandled-exception-servicesbinding-defaultbinarymessenger-was-accesse – Sisir Mar 17 '20 at 20:15
4

Create a SplashPage that you can pass as a home route in your MaterialApp()

Inside SplashPage, for example initState() you can check for login and than push new route to a Navigator.

SplashPage can just be centered logo, with optional animation.

Tree
  • 29,135
  • 24
  • 78
  • 98
  • I know this steps, the core question is how to read my local mark isLogin in main, I got this async issue – Nicholas Jela May 22 '18 at 01:34
  • 1
    Dont read it in main, you should read it inside SplashPage. override initState() and inside call one function you mark async where you read it. In case you want to read it in main, add checkIsLogin().then( put your craetion of the app in here) – Tree May 22 '18 at 01:42
3

Load the Homepage and if the user is not logged in, then replace it with your LoginPage()

@override
  void initState() {
    super.initState();
    checkIsLogin();
 }   


Future<Null> checkIsLogin() async {
    String _token = "";
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _token = prefs.getString("token");
    if (_token != "" && _token != null) {
      print("alreay login.");
      //your home page is loaded
    }
    else
    {
      //replace it with the login page
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(builder: (context) => new LoginPage()),
      );
    }
  }
Shyju M
  • 9,387
  • 4
  • 43
  • 48
2

Here is what you can do

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() async {

  String initialRoute;

  // handle exceptions caused by making main async
  WidgetsFlutterBinding.ensureInitialized();

  // init a shared preferences variable
  SharedPreferences prefs = await SharedPreferences.getInstance();
  
  // read token
  String token = prefs.getString('token');

  // use dart's null safety operater
  if (token?.isEmpty ?? true)
    initialRoute = 'login';
  else
    initialRoute = '/';

  // create a flutter material app as usual
  Widget app = MaterialApp(
    ...
    initialRoute: initialRoute,
  );

  // mount and run the flutter app
  runApp(app);
}

For more details, you can refer to this article: https://www.ravsam.in/blog/dynamic-home-route-in-flutter-app/

Ravgeet Dhillon
  • 532
  • 2
  • 6
  • 24