(Flutter Futurebuilder) appbar title 不会在页面变化时立即加载
(Flutter Futurebuilder) the appbar title won't load as soon as the page changes
import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:flutter_app/home_page.dart';
import 'package:flutter_app/login_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:geolocator/geolocator.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String name;
@override
void initState() {
super.initState();
}
Future <void>loadPref()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return Future.delayed(Duration(seconds: 1),(){
return name=sharedPreferences.getString("useFullName");
});
}
logout()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.clear();
sharedPreferences.commit();
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => LoginPage()), (Route<dynamic> route) => false);
}
var locationMessege= "";
void getCurrentLocation()async{
var position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
var lastPosition=await Geolocator.getLastKnownPosition();
print(lastPosition);
setState(() {
locationMessege="$position.latitude,$position.longitude";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor:Colors.orangeAccent,
title: FutureBuilder(
future: loadPref(),
builder: (context, snapshot) {
if(name==null){
return Text("Loading");
}else{
return Text("$name");
}
},
),
actions: <Widget>[
FlatButton(
onPressed: () {
logout();
},
child: Text("Log Out", style: TextStyle(color: Colors.white)),
),
],
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/bg1.png"), fit: BoxFit.cover)),
child: Center(
child: Container(
padding: EdgeInsets.all(30),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
children:<Widget> [
Container(
width: 130.0,
height: 130.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/solalogo2.png"), fit: BoxFit.cover))
),
Text("GPS Location",style: TextStyle(
color: Colors.black,
fontSize: 30.0,
fontWeight: FontWeight.bold)),
Icon(Icons.location_on,
size: 46,
color: Colors.yellow,),
Text("Position:$locationMessege",style:TextStyle(
color: Colors.black,
fontSize: 20.0,
fontWeight: FontWeight.bold)),
FlatButton(onPressed:(){
getCurrentLocation();
},
color: Colors.orange,
child: Text("Get New Location",
style: TextStyle(
color: Colors.black,
),))
],
),
],
),
),
),
),
);
}
}
登录成功后跳转至此主页。我想在 appbar
标题上加载用户名,但它总是触发加载语句并且在我关闭应用程序并再次加载它之前不会加载名称。当您重新打开应用程序时,如果用户之前登录过,您将被定向到主页。我是 Flutter 的新手,这是我使用它的第二周,非常感谢任何有用的提示和建议。
更改loadPref()
方法的代码
Future <String> loadPref()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return await sharedPreferences.getString("useFullName");
}
FutureBuilder(
future: loadPref(),
builder: (context, snapshot) {
if(snapshot.hasData){
return Text("${snapshot.data}");
}else{
return Text("Loading");
}
},
)
恕我直言,对你的情况使用 FutureBuilder
有点矫枉过正。
您可以使用 then
方法代替 await
。参见 https://api.flutter.dev/flutter/dart-async/Future/then.html。
因此,像下面的代码一样更改您的 initState()
:
class _HomePageState extends State<HomePage> {
String name = ""; // Defaulting to empty
@override
void initState() {
super.initState();
SharedPreferences.getInstance().then((res) {
setState(() {
// Return string of "useFullName"
// or return empty string if "userFullName" is null
name = res.getString("useFullName")?? '';
});
});
}
}
现在,您只需将 name
变量用于 AppBar 标题即可:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor:Colors.orangeAccent,
title: Text(name),
),
...
);
}
Future <String> loadPref()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return Future.delayed(Duration(seconds: 1),()async{
return await sharedPreferences.getString("useFullName");
});
}
延迟包裹 return 使它起作用,但我完全不知道为什么它现在起作用但以前不起作用,感谢 Priyesh 建议的代码,我修改了它以获得它 运行。如果有人知道为什么它不起作用,请告诉我!谢谢。
import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:flutter_app/home_page.dart';
import 'package:flutter_app/login_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:geolocator/geolocator.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String name;
@override
void initState() {
super.initState();
}
Future <void>loadPref()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return Future.delayed(Duration(seconds: 1),(){
return name=sharedPreferences.getString("useFullName");
});
}
logout()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.clear();
sharedPreferences.commit();
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => LoginPage()), (Route<dynamic> route) => false);
}
var locationMessege= "";
void getCurrentLocation()async{
var position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
var lastPosition=await Geolocator.getLastKnownPosition();
print(lastPosition);
setState(() {
locationMessege="$position.latitude,$position.longitude";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor:Colors.orangeAccent,
title: FutureBuilder(
future: loadPref(),
builder: (context, snapshot) {
if(name==null){
return Text("Loading");
}else{
return Text("$name");
}
},
),
actions: <Widget>[
FlatButton(
onPressed: () {
logout();
},
child: Text("Log Out", style: TextStyle(color: Colors.white)),
),
],
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/bg1.png"), fit: BoxFit.cover)),
child: Center(
child: Container(
padding: EdgeInsets.all(30),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
children:<Widget> [
Container(
width: 130.0,
height: 130.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/solalogo2.png"), fit: BoxFit.cover))
),
Text("GPS Location",style: TextStyle(
color: Colors.black,
fontSize: 30.0,
fontWeight: FontWeight.bold)),
Icon(Icons.location_on,
size: 46,
color: Colors.yellow,),
Text("Position:$locationMessege",style:TextStyle(
color: Colors.black,
fontSize: 20.0,
fontWeight: FontWeight.bold)),
FlatButton(onPressed:(){
getCurrentLocation();
},
color: Colors.orange,
child: Text("Get New Location",
style: TextStyle(
color: Colors.black,
),))
],
),
],
),
),
),
),
);
}
}
登录成功后跳转至此主页。我想在 appbar
标题上加载用户名,但它总是触发加载语句并且在我关闭应用程序并再次加载它之前不会加载名称。当您重新打开应用程序时,如果用户之前登录过,您将被定向到主页。我是 Flutter 的新手,这是我使用它的第二周,非常感谢任何有用的提示和建议。
更改loadPref()
方法的代码
Future <String> loadPref()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return await sharedPreferences.getString("useFullName");
}
FutureBuilder(
future: loadPref(),
builder: (context, snapshot) {
if(snapshot.hasData){
return Text("${snapshot.data}");
}else{
return Text("Loading");
}
},
)
恕我直言,对你的情况使用 FutureBuilder
有点矫枉过正。
您可以使用 then
方法代替 await
。参见 https://api.flutter.dev/flutter/dart-async/Future/then.html。
因此,像下面的代码一样更改您的 initState()
:
class _HomePageState extends State<HomePage> {
String name = ""; // Defaulting to empty
@override
void initState() {
super.initState();
SharedPreferences.getInstance().then((res) {
setState(() {
// Return string of "useFullName"
// or return empty string if "userFullName" is null
name = res.getString("useFullName")?? '';
});
});
}
}
现在,您只需将 name
变量用于 AppBar 标题即可:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor:Colors.orangeAccent,
title: Text(name),
),
...
);
}
Future <String> loadPref()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return Future.delayed(Duration(seconds: 1),()async{
return await sharedPreferences.getString("useFullName");
});
}
延迟包裹 return 使它起作用,但我完全不知道为什么它现在起作用但以前不起作用,感谢 Priyesh 建议的代码,我修改了它以获得它 运行。如果有人知道为什么它不起作用,请告诉我!谢谢。