You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.currentUser getter(需要处理null)或者authStateChanges()流;
  • 依赖管理:如果用原生dart的switchMap,可以不用rxdart,不过rxdart提供了更多实用的流操作符,按需选择就行。

内容的提问来源于stack exchange,提问作者Ruud van Engelenhoven

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 10:42:49