【问题标题】:Flutter read shared preferences in main then decide which startup page?Flutter 在 main 中读取共享首选项,然后决定哪个启动页面?
【发布时间】:2018-10-31 16:21:30
【问题描述】:

我想在main中判断启动哪个页面(其实是登录页面和首页)。所以我必须阅读首选项中的 isLogin 。如何在 main 中做到这一点?

我绑定了这些代码:

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
  ));
}

在上面的代码中,isLogin 是一个全局变量。出现错误:

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)

似乎在 main 中调用 async 有问题,如何让它工作?

【问题讨论】:

  • 为了获得更好的性能,请不要触摸您的主要功能。

标签: async-await dart flutter


【解决方案1】:

创建一个SplashPage,您可以将其作为您的MaterialApp() 中的主路由传递

在 SplashPage 中,例如 initState(),您可以检查登录,然后将新路由推送到 Navigator

SplashPage 可以只是居中的标志,带有可选的动画。

【讨论】:

  • 我知道这个步骤,核心问题是如何在main中读取我的本地标记isLogin,我遇到了这个异步问题
  • 不要在 main 中阅读,您应该在 SplashPage 中阅读。覆盖 initState() 并在内部调用一个函数,您将在读取它的位置标记为异步。如果您想在 main 中阅读它,请添加 checkIsLogin().then( 将您的应用程序放在此处)
  • 天哪。我想你解决了我的难题。完成后我会更新一些代码。
【解决方案2】:

你需要等待 checkIsLogin。

这是我的代码:

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());
}

【讨论】:

  • 我喜欢这个..我不知道主要功能可以是异步的
  • 如果您遇到与ServiceBinding 相关的异常,则只需调用WidgetsFlutterBinding.ensureInitialized(); 作为主函数的初始行。检查这个:stackoverflow.com/questions/57689492/…
【解决方案3】:

加载主页,如果用户未登录,则将其替换为您的 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()),
      );
    }
  }

【讨论】:

  • 如果主页本身就是登录页面怎么办?
【解决方案4】:

这就是我所做的,

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());
  });
}

然后在Material App Build中

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

_checkUserLoggedIn 函数

bool _checkUserLoggedIn() {
    return _storageService.getFromShared('isLoggedIn'); //  Just a get method from shared preferences
}

【讨论】:

  • 可能 OP 正在谈论这个 SharedPreferences 插件:pub.dev/packages/shared_preferences。 1) 你在哪里可以找到插件文档中的.then((instance) { 部分? 2)在_checkUserLoggedIn()函数内部,你从哪里得到storageService变量?
  • @IstiaqueAhmed 嘿伙计,很抱歉耽搁了这么久,现在才看到评论 1)它已经在那里了,无需搜索。在官方文档中,它说使用“​​await SharedPreferences.getInstance()”来获取实例。使用 await 意味着它是一个承诺 -> 我们也可以将其用作 .then((instance)) (如异步方式)。 2)我在这里使用 _storageService 作为占位符以及我如何处理我的应用程序中的依赖项(我的方式:D)。它只是一个单例服务,我用来抽象通过 SharedPreferences 实现的存储服务的工作
【解决方案5】:

你可以这样做

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);
}

更多详情可以参考这篇文章:https://www.ravsam.in/blog/dynamic-home-route-in-flutter-app/

【讨论】:

    猜你喜欢
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    • 2018-06-25
    • 1970-01-01
    • 2020-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多