如何使构建函数在 Flutter 中等待异步函数?
How to make build function wait async function in Flutter?
小部件构建函数不等待异步函数更新变量值,这对于脚手架 webview link 是必不可少的。我试图将异步函数移动到代码的不同部分,但似乎没有任何效果。将变量打印到控制台时,首先打印空值,然后打印实际值。这里有什么问题?
class ProfilePage extends StatefulWidget {
const ProfilePage({Key? key}) : super(key: key);
@override
State<ProfilePage> createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
var phone;
var password;
@override
void initState() {
super.initState();
retrieveStringValue();
}
retrieveStringValue() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
password = prefs.getString("password");
phone = prefs.getString("phone");
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: false,
body: SafeArea(
child: WebView(
javascriptMode: JavascriptMode.unrestricted,
initialUrl:
'https://turon.com/app_login.php?phone=$phone&password=$password',
),
),
);
}
}
您可以为此使用 FutureBuilder
。您还可以稍微简化它并使用 StatelessWidget
.
在这里,我将您的 retrieveStringValue
函数更改为 return a Map
,其中包含 FutureBuilder
将用于显示数据的存储值。
class ProfilePage extends StatelessWidget {
const ProfilePage({Key? key}) : super(key: key);
Future<Map<String, String>?> retrieveStringValue() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final password = prefs.getString("password");
final phone = prefs.getString("phone");
final bool hasData = password != null && phone != null;
if (hasData) {
return {
'password': password,
'phone': phone
}; // this return value is accessed via snapshot.data in FutureBuilder
} else {
return null; // null tells FutureBuilder that no data is stored
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: false,
body: SafeArea(
child: FutureBuilder(
future: retrieveStringValue(), // returns a Map with the stored values
builder: (context, snapshot) {
if (snapshot.hasData) {
final map = snapshot.data! as Map<String, String>;
final password = map['password'];
final phone = map['phone'];
return WebView(
javascriptMode: JavascriptMode.unrestricted,
initialUrl:
'https://turon.com/app_login.php?phone=$phone&password=$password',
);
} else {
return Center(child: CircularProgressIndicator()); // or an indicator that no data is stored
}
},
),
),
);
}
}
小部件构建函数不等待异步函数更新变量值,这对于脚手架 webview link 是必不可少的。我试图将异步函数移动到代码的不同部分,但似乎没有任何效果。将变量打印到控制台时,首先打印空值,然后打印实际值。这里有什么问题?
class ProfilePage extends StatefulWidget {
const ProfilePage({Key? key}) : super(key: key);
@override
State<ProfilePage> createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
var phone;
var password;
@override
void initState() {
super.initState();
retrieveStringValue();
}
retrieveStringValue() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
password = prefs.getString("password");
phone = prefs.getString("phone");
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: false,
body: SafeArea(
child: WebView(
javascriptMode: JavascriptMode.unrestricted,
initialUrl:
'https://turon.com/app_login.php?phone=$phone&password=$password',
),
),
);
}
}
您可以为此使用 FutureBuilder
。您还可以稍微简化它并使用 StatelessWidget
.
在这里,我将您的 retrieveStringValue
函数更改为 return a Map
,其中包含 FutureBuilder
将用于显示数据的存储值。
class ProfilePage extends StatelessWidget {
const ProfilePage({Key? key}) : super(key: key);
Future<Map<String, String>?> retrieveStringValue() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final password = prefs.getString("password");
final phone = prefs.getString("phone");
final bool hasData = password != null && phone != null;
if (hasData) {
return {
'password': password,
'phone': phone
}; // this return value is accessed via snapshot.data in FutureBuilder
} else {
return null; // null tells FutureBuilder that no data is stored
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: false,
body: SafeArea(
child: FutureBuilder(
future: retrieveStringValue(), // returns a Map with the stored values
builder: (context, snapshot) {
if (snapshot.hasData) {
final map = snapshot.data! as Map<String, String>;
final password = map['password'];
final phone = map['phone'];
return WebView(
javascriptMode: JavascriptMode.unrestricted,
initialUrl:
'https://turon.com/app_login.php?phone=$phone&password=$password',
);
} else {
return Center(child: CircularProgressIndicator()); // or an indicator that no data is stored
}
},
),
),
);
}
}