Flutter Fire中如何从DocumentSnapshot获取指定字段并解决StreamBuilder类型报错
问题解决说明
错误核心原因
- 你调用
get()方法获取单文档数据,返回的是Future<DocumentSnapshot>类型,既不是Stream类型,也不是你在StreamBuilder中声明的QuerySnapshot类型 - 要使用Stream做实时监听,需要调用
snapshots()方法替代get() QuerySnapshot是集合多文档查询的返回类型,你查询的是单个指定uid的文档,返回类型是DocumentSnapshot,两者不能混用
完整修改代码
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:quicktodo/model/authservice.dart'; // 修正类名和构造函数命名不匹配的问题 class Analytics extends StatefulWidget { const Analytics({Key? key}) : super(key: key); String uida = FirebaseAuth.instance.currentUser!.uid; @override _AnalyticsState createState() => _AnalyticsState(); } class _AnalyticsState extends State<Analytics> { // 明确声明stream类型 late final Stream<DocumentSnapshot<Map<String, dynamic>>> _stream; String uid = FirebaseAuth.instance.currentUser!.uid; @override void initState() { super.initState(); // 用snapshots()获取实时数据流,替代get() _stream = FirebaseFirestore.instance.collection('events').doc(uid).snapshots(); } @override Widget build(BuildContext context) { final authService = Provider.of<AuthClass>(context); return Scaffold( appBar: AppBar( leading: IconButton( icon: const Icon(Icons.logout), tooltip: 'List of your activities', onPressed: () { authService.signout(); }, ), title: const Text('Activity list'), actions: <Widget>[ IconButton( icon: const Icon(Icons.add), tooltip: 'List of your activities', onPressed: () {}, ), ], ), // 修正StreamBuilder泛型为DocumentSnapshot body: StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>( stream: _stream, builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot<Map<String, dynamic>>> snapshot) { if (snapshot.hasError) { return const Text('Something went wrong'); } if (snapshot.connectionState == ConnectionState.waiting) { return const Text("Loading"); } // 单文档直接取数据,不需要遍历docs列表 Map<String, dynamic> docData = snapshot.data!.data()!; // 如果文档中存储的是活动列表,可以遍历列表字段生成子项,这里以展示eventone字段为例 return ListView( children: [ Container( child: Text(docData['eventone'] ?? ''), ) // 其余要展示的字段可自行添加对应组件 ], ); }, ), ); } }
额外说明
如果你不需要实时监听数据变化,只是一次性拉取数据展示,可以把StreamBuilder换成FutureBuilder,_stream变量改为Future<DocumentSnapshot>类型,保持调用get()即可。
内容的提问来源于stack exchange,提问作者akhicoda
相关产品推荐
相关产品推荐

