Flutter基于共享首选项设置启动页面

时间:2019-03-18 01:07:55

标签: dart flutter

我一直在尝试根据我的“共享首选项”设置加载不同的页面。

基于stackoverflow中的几篇文章,我得出以下解决方案:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:testing/screens/login.dart';
import 'package:testing/screens/home.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Widget page = Login();

  Future getSharedPrefs() async {

    String user = Preferences.local.getString('user');

    if (user != null) {
      print(user);
      this.page = Home();
    }
  }

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

    this.getSharedPrefs();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: this.page);
  }
}

class Preferences {
  static SharedPreferences local;

  /// Initializes the Shared Preferences and sets the info towards a global variable
  static Future init() async {
    local = await SharedPreferences.getInstance();
  }
}

变量user不为空,因为print(user)返回了预期的值,但是login屏幕始终处于打开状态。

2 个答案:

答案 0 :(得分:2)

您的问题是,在getSharedPrefs将来完成之前,您的构建方法将返回。 getSharedPrefs一旦被调用就立即返回,因为它是异步的,并且您由于不等待而将其视为“ Fire and Forget”。看到您无法等待有意义的initState函数。

在这里您要使用FutureBuilder小部件。创建一个返回布尔值(如果需要更多状态,则为枚举)的Future并将future构建器用作您的家庭孩子,以返回正确的小部件。

创造你的未来

Future<bool> showLoginPage() async {
  var sharedPreferences = await SharedPreferences.getInstance();

  // sharedPreferences.setString('user', 'hasuser');

  String user = sharedPreferences.getString('user');

  return user == null;
}

当用户为null时,它将返回true。在“未来”构建器中使用此Future来监听值的变化并做出相应的响应。

 @override
  Widget build(BuildContext context) {
    return MaterialApp(home: FutureBuilder<bool>(
     future: showLoginPage(),
     builder: (buildContext, snapshot) {
       if(snapshot.hasData) {
         if(snapshot.data){
           // Return your login here
        return Container(color: Colors.blue);
      }

      // Return your home here
      return Container(color: Colors.red);
    } else {

      // Return loading screen while reading preferences
      return Center(child: CircularProgressIndicator());
    }
  },
));
}

我运行了这段代码,它运行正常。当需要登录时,您应该会看到一个蓝屏,当有用户在场时,您会看到一个红屏。取消注释showLoginPage中的行以进行测试。

答案 1 :(得分:0)

有很多方法可以做到这一点。 假设您有一些路由和一个名为Initialized的布尔值SharedPreference密钥。 调用 runApp()方法之前,需要使用 WidgetsFlutterBinding.ensureInitialized()函数。

void main() async {
  var mapp;
  var routes = <String, WidgetBuilder>{
    '/initialize': (BuildContext context) => Initialize(),
    '/register': (BuildContext context) => Register(),
    '/home': (BuildContext context) => Home(),
  };
  print("Initializing.");
  WidgetsFlutterBinding.ensureInitialized();
  await SharedPreferencesClass.restore("initialized").then((value) {
    if (value) {
      mapp = MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'AppName',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        routes: routes,
        home: Home(),
      );
    } else {
      mapp = MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'AppName',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        routes: routes,
        home: Initialize(),
      );
    }
  });
  print("Done.");
  runApp(mapp);
}

SharedPreference类代码:

class SharedPreferencesClass {
  static Future restore(String key) async {
    final SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
    return (sharedPrefs.get(key) ?? false);
  }

  static save(String key, dynamic value) async {
    final SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
    if (value is bool) {
      sharedPrefs.setBool(key, value);
    } else if (value is String) {
      sharedPrefs.setString(key, value);
    } else if (value is int) {
      sharedPrefs.setInt(key, value);
    } else if (value is double) {
      sharedPrefs.setDouble(key, value);
    } else if (value is List<String>) {
      sharedPrefs.setStringList(key, value);
    }
  }
}