flutter - 如何在 Widget build() 之前获取 SharedPrefences 的值,即在构建 UI 之前。?
问题描述
最初当屏幕加载它时显示错误
A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 269 pos 10: 'data != null't
几秒钟后,该值将存储到 _emailSF 变量中。
这是 Stateful 小部件类 HomeScreen 的实例,此任务的主要要求是在 UI 构建发生之前获取 SharedPreferences 字段的值。
getValuesSF 是初始化变量 _emailSF 的值的异步函数;
class DrawerWidget extends State<HomeScreen> {
final String title;
String _emailSF;
DrawerWidget({this.title});
@override
void initState() {
print("*****TAG:HomeScreen*****: initState");
super.initState();
getValuesSF();
}
@override
Widget build(BuildContext context) {
print("*****TAG:HomeScreen*****: $_emailSF");
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
iconTheme: IconThemeData(color: Colors.blue),
title: Text(
"Flutter For Beginners",
style: TextStyle(color: Colors.blue),
),
centerTitle: true,
),
drawer: Drawer(
// Add a ListView to the drawer. This ensures the user can scroll
// through the options in the drawer if there isn't enough vertical
// space to fit everything.
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
AppDrawer().createHeader(_emailSF),
AppDrawer().createDrawerItem(icon: Icons.home, text: 'Home'),
ExpansionTile(
leading: Icon(Icons.mobile_screen_share),
title: Text(
"Examples",
style: TextStyle(fontSize: 16),
),
children: <Widget>[
ListTile(
contentPadding: EdgeInsets.only(left: 70),
title: Text(
"Stack",
textAlign: TextAlign.start,
),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, '/stack');
}),
ListTile(
contentPadding: EdgeInsets.only(left: 70),
title: Text(
"Scoped Model",
textAlign: TextAlign.start,
),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, '/counter');
}),
ListTile(
contentPadding: EdgeInsets.only(left: 70),
title: Text(
"Http Request",
textAlign: TextAlign.start,
),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, '/fetch');
}),
ListTile(
contentPadding: EdgeInsets.only(left: 70),
title: Text(
"StatefullWidget",
textAlign: TextAlign.start,
),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, '/StateFullWidget');
})
],
),
AppDrawer().createDrawerItem(
icon: Icons.open_with,
text: 'Product',
onTap: () => Navigator.pushNamed(context, '/product')),
Divider(),
AppDrawer().createDrawerItem(
icon: Icons.mobile_screen_share,
text: 'Logout',
onTap: () => Navigator.pushNamed(context, '/product')),
],
),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[Center(child: Text("Home Screen"))],
),
),
);
}
getValuesSF() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
// Return String
setState(() => this._emailSF = prefs.getString('email'));
print(
"*****TAG:LoginScreen*****:------getValuesSF() Email-------${prefs.getString('email')}");
//Return double
}
}
解决方案
没有办法阻止构建,但是您可以选择仅在从共享首选项加载 _emailSF 后显示标题,如下所示。
class DrawerWidget extends State<HomeScreen> {
final String title;
String _emailSF;
DrawerWidget({this.title});
@override
void initState() {
print("*****TAG:HomeScreen*****: initState");
super.initState();
getValuesSF();
}
@override
Widget build(BuildContext context) {
print("*****TAG:HomeScreen*****: $_emailSF");
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
iconTheme: IconThemeData(color: Colors.blue),
title: Text(
"Flutter For Beginners",
style: TextStyle(color: Colors.blue),
),
centerTitle: true,
),
drawer: Drawer(
// Add a ListView to the drawer. This ensures the user can scroll
// through the options in the drawer if there isn't enough vertical
// space to fit everything.
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
if(_emailSF != null)
AppDrawer().createHeader(_emailSF),
AppDrawer().createDrawerItem(icon: Icons.home, text: 'Home'),
ExpansionTile(
leading: Icon(Icons.mobile_screen_share),
title: Text(
"Examples",
style: TextStyle(fontSize: 16),
),
children: <Widget>[
ListTile(
contentPadding: EdgeInsets.only(left: 70),
title: Text(
"Stack",
textAlign: TextAlign.start,
),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, '/stack');
}),
ListTile(
contentPadding: EdgeInsets.only(left: 70),
title: Text(
"Scoped Model",
textAlign: TextAlign.start,
),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, '/counter');
}),
ListTile(
contentPadding: EdgeInsets.only(left: 70),
title: Text(
"Http Request",
textAlign: TextAlign.start,
),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, '/fetch');
}),
ListTile(
contentPadding: EdgeInsets.only(left: 70),
title: Text(
"StatefullWidget",
textAlign: TextAlign.start,
),
onTap: () {
Navigator.pop(context);
Navigator.pushNamed(context, '/StateFullWidget');
})
],
),
AppDrawer().createDrawerItem(
icon: Icons.open_with,
text: 'Product',
onTap: () => Navigator.pushNamed(context, '/product')),
Divider(),
AppDrawer().createDrawerItem(
icon: Icons.mobile_screen_share,
text: 'Logout',
onTap: () => Navigator.pushNamed(context, '/product')),
],
),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[Center(child: Text("Home Screen"))],
),
),
);
}
getValuesSF() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
// Return String
setState(() => this._emailSF = prefs.getString('email'));
print(
"*****TAG:LoginScreen*****:------getValuesSF() Email-------${prefs.getString('email')}");
//Return double
}
}
有什么改变?
而不是AppDrawer().createHeader(_emailSF)
,使用if(_emailSF != null) AppDrawer().createHeader(_emailSF),
推荐阅读
- nativescript - ValueError:构建nativescript应用程序时没有结束引号
- azure - 使用 Azure Cli 从 Azure 订阅中删除部署
- html - 如何在 CSS 网格间隙之间填充文本?
- julia - 如何使规范化以适用于 Julia 中的所有类型的数组?
- winforms - 如何拦截winform文本框选择右键复制
- swift - 我如何在中断状态下快速获取我的代码行而不是后台进程
- android - Android:如何为暗模式切换主题?
- python - 我如何保存复选框中的输入,其中当我只选中复选框上的一个选项时,它给了我一个错误
- javascript - DataLayer.push 不适用于外部 JavaScript
- java - 在 Java 中从 System.in 获取 int 数组的简单方法