如何访问构建方法flutter中的共享首选项字符串



我正试图在我的构建方法中访问共享首选项中的userEmail。以下是一些上下文代码:

Widget build(BuildContext context) {
final prefs = await SharedPreferences.getInstance();
final userEmail = prefs.getString('userEmail') ?? '';
...
Return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: StreamBuilder<QuerySnapshot>(
stream: _firestore.collection(userEmail).orderBy('time', descending: false).snapshots(),
...

我遇到的问题是,出现了一个突出显示await的错误。当我用光标悬停在它上面以获取更多信息时,它会显示The await expression can only be used in an async function. Try marking the function body with either 'async' or 'async*'.

然后可以选择添加"async"修饰符。所以我点击了它,它将代码转换为:

Future<Widget> build(BuildContext context) async {
...

这会导致另一条错误消息:'_HomeScreenState.build' ('Future<Widget> Function(BuildContext)') isn't a valid override of 'State.build' ('Widget Function(BuildContext)').

有什么想法可以解决这个问题吗?我已尝试使用提供程序包保存userEmail。当用户第一次登录或注册时,这非常有效,但如果热重新加载,流就不起作用。

您可以使用WidgetsBinding.instance.addPostFrameCallback,这有助于在帧期间运行回调,就在持久帧回调之后(即主渲染管道已刷新时(。如果一个帧正在进行中,并且帧后回调尚未执行,则注册的回调仍将在帧期间执行。否则,注册的回调将在下一帧中执行。

在代码中,您可以像这样使用它。

@override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) async {
final prefs = await SharedPreferences.getInstance();
final userEmail = prefs.getString('userEmail') ?? '';
});

希望这能回答你的问题。

长话短说,您不应该在构建方法中执行任何副作用。参见此处


class MyWidget extends StatefulWidget {

@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late final prefs ;
@override
void initState() async{
super.initState();
prefs  = await SharedPreferences.getInstance();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: prefs,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if(snapshot.hasData){}else if (snapshot.hasError)
return Center(child: CircularProgressIndicator());

},);
}
}

由于您的构建方法可以被多次调用,因此您不应该执行网络调用或调用复杂的方法,因为正如文档所说。此方法可以并且将被多次调用。

在您的案例中,我使用FutureBuilder来处理未来的状态,并在initState中等待它,initState是一个有状态的小部件。

查看本文了解更多信息

正如@croxx5f和@AhmetKAYGISIZ所建议的,我最终使用FutureBuilder来解决这个问题。非常感谢你们两个在这方面的帮助。

以下是其他陷入这个问题的人的最终代码:

class MyWidget extends StatefulWidget {

@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
var prefs;
@override
void initState() {
super.initState();
getUserEmailFromSharedPrefs();
}
Future<String> getUserEmailFromSharedPrefs() async {
prefs = await SharedPreferences.getInstance();
final userEmail = prefs.getString('userEmail') ?? '';
return userEmail;
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: getUserEmailFromSharedPrefs(),
builder: (context, AsyncSnapshot<String> snapshot) {
if(snapshot.hasData) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: StreamBuilder<QuerySnapshot>(
stream: _firestore.collection(snapshot.data).orderBy('time', descending: false).snapshots(),
...

总之,我将我的streambuilder封装在一个futurebuilder中。

最新更新