我一直在尝试根据我的“共享首选项”设置加载不同的页面。
基于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
屏幕始终处于打开状态。
答案 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);
}
}
}