Flutter:当内容从 Google Firestore 到达时如何更新小部件?
Flutter: How to update widgets when their content arrives from Google Firestore?
好的,我的任务是,
1. 从 Firestore 下载记录,
2. 将其处理成状态变量
3. 将数据注入小部件。
我尝试通过在 initState 中下载内容来执行此操作,我将其设为异步,但是在 Firestore 下载完成之前调用了构建方法,我没有为小部件准备好信息,它崩溃了。
我读到,当 Widget 在布局后预计会发生变化时,我应该为小部件使用 Builder 包装器。这让我想到了这个:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Job details")), // TODO might have to modify to accomodate edits
body: _buildBody(context, widget.job.country, widget.job.area, widget.job.jobDetailedId, widget.job),
);
}
所以我正在调用带有 Builder 上下文的 buildBody,似乎我无法访问我的 this.job class 对象(为什么?!)所以我传递了一些关键参数以获取 Firestore记录.
_buildBody 的目的是下载 firestore 记录,而不使用 ASYNC await。但它从不执行
以外的任何代码
.then((jobrecord {
Widget _buildBody(BuildContext context, String countryCode, String area, String jobDetailedId) {
Job detailedJob;
Firestore.instance.collection("$countryCode/$area/JobsDetailed").document(jobDetailedId).get().then((jobRecord) {
return Builder(builder: (BuildContext context) {
if(jobRecord == null) {
return Text("Document doesn't exist");
}
else {
detailedJob = Job.fromSnapshot(jobRecord);
detailedJob.jobDetailedId = jobRecord.documentID;
return _screenBuild(context, detailedJob);
}
});
});
}
Widget _screenBuild(BuildContext context, Job detailedJob) {
return Text(detailedJob.description);
}
我以为 .then 会在 Firestore 返回文档时触发,但它没有触发。
这是解决问题的最好、最清晰的方法吗?使用 Future 会更好吗?或者 Asnc await from initState(),然后使用 setState()?
这段代码应该可以完成工作。
Widget _buildBody(BuildContext context, String countryCode, String area, String jobDetailedId) {
Job detailedJob;
return StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance.collection("$countryCode/$area/JobsDetailed").document(jobDetailedId).snapshots(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else {
var jobRecord = snapshot.data.data; // contains document fields
if(jobRecord == null) {
return Text("Document doesn't exist");
}
else {
detailedJob = Job.fromSnapshot(snapshot.data);
detailedJob.jobDetailedId = jobRecord.documentID;
return _screenBuild(context, detailedJob);
}
}
});
}
好的,我的任务是, 1. 从 Firestore 下载记录, 2. 将其处理成状态变量 3. 将数据注入小部件。
我尝试通过在 initState 中下载内容来执行此操作,我将其设为异步,但是在 Firestore 下载完成之前调用了构建方法,我没有为小部件准备好信息,它崩溃了。
我读到,当 Widget 在布局后预计会发生变化时,我应该为小部件使用 Builder 包装器。这让我想到了这个:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Job details")), // TODO might have to modify to accomodate edits
body: _buildBody(context, widget.job.country, widget.job.area, widget.job.jobDetailedId, widget.job),
);
}
所以我正在调用带有 Builder 上下文的 buildBody,似乎我无法访问我的 this.job class 对象(为什么?!)所以我传递了一些关键参数以获取 Firestore记录.
_buildBody 的目的是下载 firestore 记录,而不使用 ASYNC await。但它从不执行
以外的任何代码.then((jobrecord {
Widget _buildBody(BuildContext context, String countryCode, String area, String jobDetailedId) {
Job detailedJob;
Firestore.instance.collection("$countryCode/$area/JobsDetailed").document(jobDetailedId).get().then((jobRecord) {
return Builder(builder: (BuildContext context) {
if(jobRecord == null) {
return Text("Document doesn't exist");
}
else {
detailedJob = Job.fromSnapshot(jobRecord);
detailedJob.jobDetailedId = jobRecord.documentID;
return _screenBuild(context, detailedJob);
}
});
});
}
Widget _screenBuild(BuildContext context, Job detailedJob) {
return Text(detailedJob.description);
}
我以为 .then 会在 Firestore 返回文档时触发,但它没有触发。
这是解决问题的最好、最清晰的方法吗?使用 Future 会更好吗?或者 Asnc await from initState(),然后使用 setState()?
这段代码应该可以完成工作。
Widget _buildBody(BuildContext context, String countryCode, String area, String jobDetailedId) {
Job detailedJob;
return StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance.collection("$countryCode/$area/JobsDetailed").document(jobDetailedId).snapshots(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else {
var jobRecord = snapshot.data.data; // contains document fields
if(jobRecord == null) {
return Text("Document doesn't exist");
}
else {
detailedJob = Job.fromSnapshot(snapshot.data);
detailedJob.jobDetailedId = jobRecord.documentID;
return _screenBuild(context, detailedJob);
}
}
});
}