Flutter中如何从Firebase Firestore获取所有用户传感器数据
解决Firestore获取所有用户传感器数据的问题
问题分析
当前代码中getUsersDataList方法使用无参的.doc()会生成一个全新的随机ID文档引用,而非访问sensorData集合下已存在的用户文档,导致无法获取所有用户的传感器数据。要实现需求,需要先遍历sensorData集合的所有用户文档,再逐个读取每个文档下的userData子集合数据。
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:health_monitoring_app/auth/auth_service.dart'; import 'package:health_monitoring_app/database/database_helper.dart'; import 'package:health_monitoring_app/model/sensor_data_model.dart'; import 'package:health_monitoring_app/provider/sensor_data_provider.dart'; import 'package:health_monitoring_app/view/user_data_list.dart'; import 'package:health_monitoring_app/view/welcome_screen.dart'; import 'package:provider/provider.dart'; class DoctorDashboard extends StatefulWidget { const DoctorDashboard({Key? key}) : super(key: key); static const String routeNames = '/DoctorDashboard'; @override State<DoctorDashboard> createState() => _DoctorDashboardState(); } class _DoctorDashboardState extends State<DoctorDashboard> { final user = AuthService.currentUser; late SensorDataProvider _sensorDataProvider; // 修正类型为SensorDataModel列表,避免后续类型转换问题 List<SensorDataModel> _dataList = []; bool _isLoading = true; @override void didChangeDependencies() { _sensorDataProvider = Provider.of<SensorDataProvider>(context); super.didChangeDependencies(); getUsersDataList(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.blue.shade900, ), body: _isLoading ? const Center(child: CircularProgressIndicator()) : ListView.builder( itemCount: _dataList.length, itemBuilder: (context, index) { return UserDataList(_dataList[index]); }, ), drawer: Drawer( child: ListView( children: [ DrawerHeader( decoration: BoxDecoration( color: Colors.blue.shade900, ), child: Center( child: Text( '${user?.email}', style: const TextStyle(color: Colors.white), ), )), ListTile( onTap: _doctorSignOut, leading: const Icon(Icons.logout), title: const Text('Sign Out'), ) ], ), ), ); } void _doctorSignOut() { AuthService.signOut().then((_) { Navigator.pushReplacementNamed(context, WelcomeScreen.routeNames); }); } Future getUsersDataList() async { List<SensorDataModel> allUserData = []; // 1. 获取sensorData集合下的所有用户文档 final usersSnapshot = await DatabaseHelper.db.collection('sensorData').get(); // 2. 遍历每个用户文档,读取对应的userData子集合 for (var userDoc in usersSnapshot.docs) { final userDataSnapshot = await userDoc.reference .collection('userData') .orderBy('timestamp', descending: true) .get(); // 3. 将子集合数据转换为模型并合并到总列表 var userDataList = userDataSnapshot.docs .map((doc) => SensorDataModel.fromSnapshot(doc)) .toList(); allUserData.addAll(userDataList); } // 4. 更新UI setState(() { _dataList = allUserData; _isLoading = false; }); } }
关键修改点
- 移除无参
.doc(),改为先获取sensorData集合的所有文档快照 - 遍历每个用户文档,读取其下的
userData子集合数据 - 合并所有用户的传感器数据到统一列表
- 添加加载状态
_isLoading,优化用户体验 - 修正
_dataList的类型为List<SensorDataModel>,消除类型转换警告
注意事项
- 确保Firestore安全规则允许当前Admin账号读取
sensorData集合及其所有子集合,示例规则如下:match /sensorData/{userId}/userData/{dataId} { allow read: if request.auth != null && request.auth.token.admin == true; } - 若用户数据量较大,建议采用分页加载(结合
limit()和startAfterDocument()),避免一次性加载过多数据导致性能问题 - 可以添加错误捕获逻辑,处理网络异常或权限不足的情况
内容的提问来源于stack exchange,提问作者Mehedi Hasan
相关产品推荐
相关产品推荐

