如何在 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 变量中。

这是有状态小部件类主屏幕的实例, 此任务的主要要求是在 UI 构建发生之前获取共享首选项字段的值。

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),

最新更新