Flutter页面间传递Article ID实现单篇文章查看及错误解决
Flutter Firestore文章列表跳转单篇页面错误修复
我通过Model类从Firestore获取文章列表并用ListView展示,希望用户点击View按钮时,把对应文章的ID传到单篇文章页面展示内容,但Navigator跳转环节出错,相关代码和错误截图如下:

问题原因分析
- 列表页面跳转时使用了未定义的
article.id变量,实际应该用列表中当前项的ID - 单篇文章页面未接收传递的ID参数,无法获取目标文章标识
- 单篇页面直接使用未定义的变量渲染UI,且错误地获取整个文章列表而非单篇数据
修复后的列表页面代码
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:neerogi/screens/Articles/Admin/viewOne_articles.dart'; import '../articlesModel.dart'; class ViewArticlesScreens extends StatefulWidget { const ViewArticlesScreens({Key? key}) : super(key: key); @override State<ViewArticlesScreens> createState() => _ViewArticlesScreensState(); } class _ViewArticlesScreensState extends State<ViewArticlesScreens> { Future<List<Articles>> fetchRecords() async { var records = await FirebaseFirestore.instance.collection('articles').get(); return mapRecords(records); } List<Articles> mapRecords(QuerySnapshot<Map<String, dynamic>> records) { var _list = records.docs .map( (article) => Articles( id: article.id, topic: article['topic'], description: article['description'], url: article['url'], ), ) .toList(); return _list; } @override void initState() { super.initState(); } @override Widget build(BuildContext context) { double height = MediaQuery.of(context).size.height; double width = MediaQuery.of(context).size.width; return Scaffold( body: Column( children: [ SingleChildScrollView( child: Column( children: <Widget>[ const SizedBox(height: 10), SizedBox( width: width * 0.94, height: height * 0.90, child: FutureBuilder<List<Articles>>( future: fetchRecords(), builder: (context, snapshot) { if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } else if (!snapshot.hasData) { return const Center(child: CircularProgressIndicator()); } else { List<Articles> data = snapshot.data ?? []; return ListView.builder( itemCount: data.length, itemBuilder: (context, index) { final currentArticle = data[index]; return SizedBox( height: 100, child: Column( children: <Widget>[ ListTile( leading: Image.network( currentArticle.url, height: 30, fit: BoxFit.cover, ), title: Text(currentArticle.topic), subtitle: Text(currentArticle.description), trailing: ElevatedButton( child: const Text('View'), onPressed: () { Navigator.of(context).push( MaterialPageRoute( builder: (context) => ViewOneArticleScreen( articleId: currentArticle.id, ))); }, )) ], ), ); }); } })) ], ), ), ], ), ); } }
修复后的单篇文章页面代码
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import '../articlesModel.dart'; class ViewOneArticleScreen extends StatefulWidget { final String articleId; const ViewOneArticleScreen({Key? key, required this.articleId}) : super(key: key); @override State<ViewOneArticleScreen> createState() => _ViewOneArticleScreenState(); } class _ViewOneArticleScreenState extends State<ViewOneArticleScreen> { Future<Articles?> fetchSingleArticle() async { var doc = await FirebaseFirestore.instance.collection('articles').doc(widget.articleId).get(); if (doc.exists) { return Articles.fromJson(doc.data()!); } return null; } @override Widget build(BuildContext context) { double height = MediaQuery.of(context).size.height; double width = MediaQuery.of(context).size.width; return Scaffold( body: FutureBuilder<Articles?>( future: fetchSingleArticle(), builder: (context, snapshot) { if (snapshot.hasError) { return Center(child: Text('加载出错: ${snapshot.error}')); } else if (!snapshot.hasData || snapshot.data == null) { return const Center(child: Text('文章不存在')); } else { final article = snapshot.data!; return Column( children: [ Image.network( article.url, height: 150, width: double.infinity, fit: BoxFit.cover, ), Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(article.topic, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)), const SizedBox(height: 8), Text(article.description), ], ), ), ], ); } }, ), ); } }
关键修复点
- 列表页面:将跳转参数改为
currentArticle.id,确保传递当前点击项的正确ID - 单篇页面:
- 添加
articleId参数接收传递的文章ID - 实现
fetchSingleArticle方法,根据ID从Firestore获取单篇数据 - 使用
FutureBuilder处理异步加载,用获取到的文章数据渲染UI
- 添加
内容的提问来源于stack exchange,提问作者Dasun Dola
相关产品推荐
相关产品推荐

