Flutter 数据显示为空,除非我做了一个小更改以强制热重新加载。为什么不是';一开始不是吗?
所以我一直在摆弄Flitter,试图创建一个基本的应用程序来看看它是如何工作的,我有一个屏幕,可以显示单个注册用户的详细信息。问题是,当我第一次导航到屏幕时,“user”对象为空,只有在我做了一些小的更改(比如对一些文本进行了强制重新加载)时,用户数据才会像变魔术一样出现 下面是我的getUser函数,它似乎按预期工作:Flutter 数据显示为空,除非我做了一个小更改以强制热重新加载。为什么不是';一开始不是吗?,flutter,dart,Flutter,Dart,所以我一直在摆弄Flitter,试图创建一个基本的应用程序来看看它是如何工作的,我有一个屏幕,可以显示单个注册用户的详细信息。问题是,当我第一次导航到屏幕时,“user”对象为空,只有在我做了一些小的更改(比如对一些文本进行了强制重新加载)时,用户数据才会像变魔术一样出现 下面是我的getUser函数,它似乎按预期工作: Future<User> getUser() async { final UserDao userDao = UserDao(); final String
Future<User> getUser() async {
final UserDao userDao = UserDao();
final String authenticationToken = await userDao.getUserToken(0);
final response = await http.get(
'http://vps746196.ovh.net/api/user/',
headers: {HttpHeaders.authorizationHeader: 'token $authenticationToken'},
);
final responseJson = json.decode(response.body);
print(responseJson[0]);
return User.fromDatabaseJson(responseJson[0]);
}
Future getUser()异步{
final UserDao UserDao=UserDao();
最终字符串authenticationToken=wait userDao.getUserToken(0);
最终响应=等待http.get(
'http://vps746196.ovh.net/api/user/',
标头:{HttpHeaders.authorizationHeader:'token$authenticationToken'},
);
final responseJson=json.decode(response.body);
打印(responseJson[0]);
返回User.fromDatabaseJson(responseJson[0]);
}
下面是我在用户屏幕上的操作:
class UserScreen extends StatefulWidget {
@override
_UserScreenState createState() => _UserScreenState();
}
class _UserScreenState extends State<UserScreen> {
User user = User();
@override
void initState() {
_getThatUser();
print(user.username);
}
_getThatUser() async {
print('Getting that user');
user = await getUser();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('The Yard Users'),
),
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 30.0),
child: Text(
'Username: ${user.username}',
style: TextStyle(
fontSize: 24.0,
),
),
),
// Logout button
Padding(
padding: EdgeInsets.fromLTRB(34.0, 20.0, 0.0, 0.0),
child: Container(
width: MediaQuery.of(context).size.width * 0.85,
height: MediaQuery.of(context).size.width * 0.16,
child: LogoutButton()
),
),
],
),
),
);
}
}
class UserScreen扩展StatefulWidget{
@凌驾
_UserScreenState createState()=>\u UserScreenState();
}
类_UserScreenState扩展状态{
User=User();
@凌驾
void initState(){
_gethatuser();
打印(user.username);
}
_getHatUser()异步{
打印(“获取该用户”);
user=wait getUser();
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本(“场地使用者”),
),
主体:容器(
子:列(
mainAxisAlignment:mainAxisAlignment.center,
crossAxisAlignment:crossAxisAlignment.center,
儿童:[
填充物(
填充:仅限边缘设置(左:30.0),
子:文本(
'用户名:${user.Username}',
样式:TextStyle(
字体大小:24.0,
),
),
),
//注销按钮
填充物(
填充:来自LTRB(34.0,20.0,0.0,0.0)的边缘设置,
子:容器(
宽度:MediaQuery.of(context).size.width*0.85,
高度:MediaQuery.of(上下文).size.width*0.16,
子项:注销按钮()
),
),
],
),
),
);
}
}
新屏幕似乎是在数据分配给用户变量之前加载的。我认为使用await命令的全部意义在于这样就不会发生这种情况。显然,我还有很多东西要学,任何帮助都将不胜感激。这是因为在呈现
文本
小部件之前,您的未来
尚未完成
您可以通过以下方式进行修复:
用户名
为空
,则显示进度指示器;如果用户名不为空
,则显示用户名
FutureBuilder
小部件:class UserScreen扩展StatefulWidget{
@凌驾
_UserScreenState createState()=>\u UserScreenState();
}
类_UserScreenState扩展状态{
未来用户;
@凌驾
void initState(){
super.initState();
futureUser=getUser();
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本(“场地使用者”),
),
主体:容器(
子级:FutureBuilder(//使用FutureBuilder小部件
future:futureUser,//分配未来
生成器:(上下文,快照){
if(snapshot.hasData){
返回列(
//显示您的布局,如果未来完成
mainAxisAlignment:mainAxisAlignment.center,
crossAxisAlignment:crossAxisAlignment.center,
儿童:[
填充物(
填充:仅限边缘设置(左:30.0),
子:文本(
'Username:${snapshot.data.Username}',//从快照获取用户名
样式:TextStyle(
字体大小:24.0,
),
),
),
//注销按钮
填充物(
填充:来自LTRB(34.0,20.0,0.0,0.0)的边缘设置,
子:容器(
宽度:MediaQuery.of(context).size.width*0.85,
高度:MediaQuery.of(上下文).size.width*0.16,
子项:LogoutButton()),
),
],
);
}否则{
return CircularProgressIndicator();//在future执行时显示进度指示器
}
},
),
),
);
}
}
编辑:
future
不应该在build
方法中调用,为什么 您可能想看看FutureBuilder
小部件。对于第一个解决方案,必须将setState
添加到\u gethatuser
中。第二,未来应该在initState
中获得,它不应该在build中调用。感谢您指出build
方法中保存的未来
,编辑了我的答案::-。我觉得我需要使用FutureBuilder的时候做了第二个选择-谢谢很多人都很有魅力。我真的不知道我必须接受答案,再次感谢!
Padding(
padding: EdgeInsets.only(left: 30.0),
child: user.username == null
? CircularProgressIndicator() // show an indicator if the username is still null
: Text(
'Username: ${user.username}',
style: TextStyle(
fontSize: 24.0,
),
),
),
class UserScreen extends StatefulWidget {
@override
_UserScreenState createState() => _UserScreenState();
}
class _UserScreenState extends State<UserScreen> {
Future<User> futureUser;
@override
void initState() {
super.initState();
futureUser = getUser();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('The Yard Users'),
),
body: Container(
child: FutureBuilder( // use a future builder widget
future: futureUser, // assign the future
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
// show your layout if future is done
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 30.0),
child: Text(
'Username: ${snapshot.data.username}', // get the username from the snapshot
style: TextStyle(
fontSize: 24.0,
),
),
),
// Logout button
Padding(
padding: EdgeInsets.fromLTRB(34.0, 20.0, 0.0, 0.0),
child: Container(
width: MediaQuery.of(context).size.width * 0.85,
height: MediaQuery.of(context).size.width * 0.16,
child: LogoutButton()),
),
],
);
} else {
return CircularProgressIndicator(); // show a progress indicator while future is executing
}
},
),
),
);
}
}