如何在Flutter的initState中从Firestore取数据并在PDF组件展示
问题分析与解决方案
你的代码目前未实现从Firestore获取数据并渲染到PDF的核心逻辑,主要问题点及修复方案如下:
核心问题
- 仅调用Firestore的
snapshots()但未订阅或获取实际数据,没有将数据保存到本地变量 - PDF生成方法
generateDocument中未集成Firestore数据获取逻辑,仅展示了日期 - 全局
dateStr未与传入的widget.date关联,可能导致集合路径错误
修复后的完整代码
import 'dart:typed_data'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import 'package:pdf/pdf.dart'; import 'package:pdf/widgets.dart' as pw; import 'package:printing/printing.dart'; class Testing extends StatefulWidget { final String date; const Testing({required this.date, Key? key}) : super(key: key); @override State<Testing> createState() => _TestingState(); } class _TestingState extends State<Testing> { // 存储从Firestore获取的失败评分数据 List<Map<String, dynamic>> failedRatings = []; // 从Firestore获取数据的异步方法 Future<void> fetchFailedRatings() async { try { // 使用传入的日期作为文档ID,获取对应集合数据 QuerySnapshot snapshot = await FirebaseFirestore.instance .collection("ratings") .doc(widget.date) .collection('failed rating') .get(); // 将查询结果转换为可直接使用的Map列表 failedRatings = snapshot.docs.map((doc) => doc.data() as Map<String, dynamic>).toList(); } catch (e) { print('获取数据失败: $e'); } } @override Widget build(BuildContext context) { return PdfPreview( canChangeOrientation: false, canDebug: false, build: (format) => generateDocument(format), ); } Future<Uint8List> generateDocument(PdfPageFormat format) async { // 先等待Firestore数据加载完成,再生成PDF await fetchFailedRatings(); final doc = pw.Document(pageMode: PdfPageMode.outlines); final font1 = await PdfGoogleFonts.openSansRegular(); final font2 = await PdfGoogleFonts.openSansBold(); doc.addPage( pw.Page( pageTheme: pw.PageTheme( pageFormat: format.copyWith( marginBottom: 20, marginLeft: 20, marginRight: 20, marginTop: 20, ), orientation: pw.PageOrientation.portrait, theme: pw.ThemeData.withFont( base: font1, bold: font2, ), ), build: (context) { return pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ // 报表标题与日期 pw.Center( child: pw.Text( '失败评分报表', style: pw.TextStyle(font: font2, fontSize: 20), ), ), pw.SizedBox(height: 10), pw.Center(child: pw.Text('日期: ${widget.date}')), pw.SizedBox(height: 20), // 渲染数据列表 failedRatings.isEmpty ? pw.Center(child: pw.Text('暂无数据')) : pw.Expanded( child: pw.ListView.builder( itemCount: failedRatings.length, itemBuilder: (ctx, index) { final rating = failedRatings[index]; return pw.Container( padding: pw.EdgeInsets.symmetric(vertical: 8, horizontal: 10), margin: pw.EdgeInsets.only(bottom: 8), decoration: pw.BoxDecoration( border: pw.Border.all(color: PdfColors.grey), borderRadius: pw.BorderRadius.circular(4), ), child: pw.Column( crossAxisAlignment: pw.CrossAxisAlignment.start, children: [ // 根据你的实际字段名修改,此处示例为userName和score pw.Text('用户名: ${rating['userName'] ?? '未知'}', style: pw.TextStyle(font: font2)), pw.Text('评分: ${rating['score'] ?? '无'}'), // 可添加更多字段展示 ], ), ); }, ), ), ], ); }, ), ); return doc.save(); } }
关键修改说明
- 规范命名:将
testing改为Testing,符合Dart类命名规范 - 数据获取:新增
fetchFailedRatings方法,通过get()一次性获取Firestore集合数据(若需实时更新可改用snapshots()监听) - PDF渲染:在
generateDocument中先等待数据加载完成,再根据数据状态渲染空数据提示或列表内容,用ListView.builder高效循环展示每条数据 - 路径修正:使用传入的
widget.date作为文档ID,确保获取对应日期的目标集合数据 - 布局优化:添加标题、边距和卡片样式,提升PDF内容可读性
使用示例:
Testing(date: '10-2024') // 替换为实际需要的日期格式
内容的提问来源于stack exchange,提问作者Marc louis Labitoria
相关产品推荐
相关产品推荐

