如何使用Flutter获取Firestore数据并实现页面跳转?
问题分析与解决方案
你的问题核心在于_open_edit_or_delete函数的实现逻辑完全错误——你在函数里创建了Visibility和StreamBuilder,但这些Widget并没有被添加到Flutter的Widget树中,所以StreamBuilder永远不会触发数据请求,自然也不会执行页面跳转的逻辑。而且更关键的是:你根本不需要重新从Firestore拉取所有新闻数据,因为当前页面已经通过widget.news拿到了要编辑的目标新闻对象!
修正后的实现方案
直接利用已有的widget.news对象,简化_open_edit_or_delete函数即可:
void _open_edit_or_delete(String selectedOption) { if (selectedOption == 'Edit') { // 直接传递当前页面已有的widget.news对象 Navigator.push( context, MaterialPageRoute(builder: (_) => FirstScreen(news: widget.news)), ); } else if (selectedOption == 'Delete') { // 这里可以添加删除逻辑,比如调用Firestore的删除方法 FireStoreServiceApi().deleteNews(widget.news.id); // 删除后可以返回上一页或者更新页面 Navigator.pop(context); } }
为什么你的原代码无法工作?
- Widget未加入Widget树:你在函数里创建的
Visibility和StreamBuilder只是局部变量,没有被返回或添加到任何显示的Widget中,所以Flutter不会执行它们的生命周期,StreamBuilder永远不会监听Firestore的数据流。 - 冗余的数据请求:当前页面已经通过
widget接收了news对象,完全没必要重新拉取所有新闻再筛选,这既浪费资源又增加了逻辑复杂度。 - 跳转逻辑位置错误:你把
Navigator.push放在了snapshot.hasError || !snapshot.hasData分支里,这意味着只有在数据加载失败或无数据时才跳转,逻辑完全颠倒了。
(可选)如果需要确保数据是最新的
如果你担心widget.news不是Firestore中的最新版本,可以通过新闻ID单独获取最新数据再跳转:
void _open_edit_or_delete(String selectedOption) async { if (selectedOption == 'Edit') { // 通过ID获取最新的新闻数据 final latestNews = await FireStoreServiceApi().getNewsById(widget.news.id); if (latestNews != null) { Navigator.push( context, MaterialPageRoute(builder: (_) => FirstScreen(news: latestNews)), ); } } else if (selectedOption == 'Delete') { await FireStoreServiceApi().deleteNews(widget.news.id); Navigator.pop(context); } }
对应的FireStoreServiceApi需要添加单个新闻获取方法:
Future<News?> getNewsById(String newsId) async { final doc = await _db.collection("news").document(newsId).get(); if (doc.exists) { return News.fromMap(doc.data, doc.documentID); } return null; } // 添加删除方法(如果需要) Future<void> deleteNews(String newsId) async { await _db.collection("news").document(newsId).delete(); }
这样就能完美实现点击Edit跳转并传递正确的新闻数据了!
内容的提问来源于stack exchange,提问作者Lahiru Madusanka
相关产品推荐
相关产品推荐

