Flutter中Firestore UID传入仓库的代码优化及流方法适配问题
优化Firebase Reminder仓库:消除重复代码&解决流数据用户筛选问题
我来帮你搞定这两个核心问题——消除重复的UID获取代码,以及解决reminders()流方法里没法筛选当前用户数据的痛点。
1. 先搞定重复代码:提取UID获取逻辑
你在多个方法里重复写了获取当前用户UID的代码,咱们把这部分逻辑抽成一个私有异步方法,所有需要的地方直接调用就行,既减少冗余,后续维护也更方便。
Future<String> _getCurrentUserId() async { final user = await FirebaseAuth.instance.currentUser(); if (user == null) { throw Exception("未找到已认证用户"); // 可以根据你的业务需求自定义错误处理 } return user.uid; }
2. 解决Stream方法的用户筛选问题
因为Stream里不能直接用await,咱们可以借助Firebase Auth的用户状态流来实现动态筛选:监听用户登录状态变化,当用户存在时,自动切换到该用户对应的Firestore reminders集合流。
具体来说,用FirebaseAuth.instance.onAuthStateChanged(新版本Firebase Auth推荐用authStateChanges())拿到用户状态流,再通过switchMap操作符把用户流转换成对应的提醒数据流。这样不仅能获取当前用户的实时数据,用户登录/登出时还能自动更新流内容,更健壮。
完整优化后的代码
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:diabetes/src/model/models.dart'; import 'package:diabetes/src/entities/entities.dart'; import 'package:diabetes/src/repositories/repositories.dart'; import 'package:rxdart/rxdart.dart'; // 使用switchMap需要依赖rxdart,也可以用dart:async原生的switchMap class FirebaseRemindersRepository implements RemindersRepository { // 把Firebase实例提取为类成员,更规范 final FirebaseFirestore _firestore = FirebaseFirestore.instance; final FirebaseAuth _auth = FirebaseAuth.instance; // 私有方法:统一获取当前用户UID Future<String> _getCurrentUserId() async { final user = await _auth.currentUser(); if (user == null) { throw Exception("未找到已认证用户"); } return user.uid; } @override Future<void> addNewReminder(Reminder reminder) async { try { final uid = await _getCurrentUserId(); return _firestore .collection("users") .doc(uid) .collection("reminders") .add(reminder.toEntity().toDocument()); } catch (error) { print(error); rethrow; // 建议重新抛出错误,让上层代码处理(比如给用户显示错误提示) } } @override Future<void> deleteReminder(Reminder reminder) async { try { final uid = await _getCurrentUserId(); return _firestore .collection("users") .doc(uid) .collection("reminders") .doc(reminder.id) .delete(); } catch (error) { print(error); rethrow; } } @override Stream<List<Reminder>> reminders() { // 监听用户状态变化,动态返回对应用户的提醒流 return _auth.onAuthStateChanged.switchMap((user) { if (user == null) { // 用户未登录时,返回空列表流 return Stream.value([]); } final uid = user.uid; return _firestore .collection("users") .doc(uid) .collection("reminders") .snapshots() .map((snapshot) { return snapshot.docs .map((doc) => Reminder.fromEntity(ReminderEntity.fromSnapshot(doc))) .toList(); }); }); } @override Future<void> updateReminder(Reminder update) async { try { final uid = await _getCurrentUserId(); return _firestore .collection("users") .doc(uid) .collection("reminders") .doc(update.id) .update(update.toEntity().toDocument()); } catch (error) { print(error); rethrow; } } }
额外小建议
- 错误处理:不要只打印错误,重新抛出错误让上层处理,能给用户更友好的反馈;
- 新版本适配:如果用的是新版Firebase,
currentUser()已过时,推荐用同步的_auth.currentUsergetter(需要处理null)或者authStateChanges()流; - 依赖管理:如果用原生dart的
switchMap,可以不用rxdart,不过rxdart提供了更多实用的流操作符,按需选择就行。
内容的提问来源于stack exchange,提问作者Ruud van Engelenhoven
相关产品推荐
相关产品推荐

