在我的带有 Firestore 和 Redux 状态管理的 flutter 应用程序中,我有一个 firestore 流查询。
当用户登录时,查询工作正常。当用户注销时,我切换到anonymousLogin。但是注销和新登录之间的时间间隔会引发错误:
颤振:----------------FIREBASE CRASHLYTICS---------------- flutter: [cloud_firestore/permission-denied] 调用者无权执行指定操作。 扑: #0 EventChannelExtension.receiveGuardedBroadcastStream (包:_flutterfire_internals/src/exception.dart:67:43) #1 MethodChannelQuery.snapshots。 (包:cloud_firestore_platform_interface/src/method_channel/method_channel_query.dart:183:18)
从文档中我意识到这是一个已知的情况,我需要处理该错误。但尽管引入了错误块并取消了订阅,错误仍然会被抛出。
我该如何处理这个问题。
查询位于服务中
class GroupService {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _db = FirebaseFirestore.instance;
StreamController<void> _logoutController = StreamController<void>();
StreamSubscription<List<Member?>>? _groupMembershipsSubscription;
GroupService();
get _getUid {
firebaseuser.User user = _auth.currentUser!;
return user.uid;
}
// Return user's group memberships from firestore
Stream<List<Member?>> getGroupMemberships() {
String uid = _getUid;
print('GroupService :: getGroupMemberships: Uid: $uid');
final docRef =
_db.collection('memberships').where('memberId', isEqualTo: uid).where(
'status',
);
return docRef.snapshots().map((snapshot) {
List<Member?> memberships = [];
if (snapshot.docs.isNotEmpty) {
memberships = snapshot.docs.map((doc) {
Member? membership =
serializers.deserializeWith(Member.serializer, doc.data());
return membership;
}).toList();
}
return memberships;
}).handleError(
(error) {
print('GroupService :: getGroupMemberships : Error: $error');
},
);
}
// Start listening to the stream and store the subscription
void startListeningToGroupMemberships({
required void Function(List<Member?>) onData,
required void Function(dynamic error) onError,
}) {
// Initialize a new logout controller
_logoutController = StreamController<void>();
// Create a new subscription
_groupMembershipsSubscription =
getGroupMemberships().takeUntil(_logoutController.stream).listen(
(memberships) {
onData(memberships);
},
onError: (error) {
onError(error);
},
);
}
// Cancel the subscription
void cancelGroupMembershipsSubscription() {
_logoutController.add(null); // Trigger takeUntil
_logoutController.close(); // Close the logout stream
_groupMembershipsSubscription?.cancel();
_groupMembershipsSubscription = null;
print('GroupService :: Subscription cancelled');
}
}
中间件执行服务调用
void Function(
Store<AppState> store,
dynamic action,
NextDispatcher next,
) _loadGroups() {
GroupService groupService = GetIt.I.get<GroupService>();
return (store, action, next) async {
next(action);
if (action is LoadGroupsAction) {
print('MW :: _loadGroups : Called on LoadGroupsAction');
groupService.startListeningToGroupMemberships(onData: (memberships) {
store.dispatch(RefreshGroupsAction());
if (memberships.isEmpty) {
store.dispatch(LoadGroupSucceededAction(null));
} else {
for (Member? m in memberships) {
try {
groupService.getGroup(m!.groupId!).then((group) {
if (m.status == MemberStatusType.active) {
store.dispatch(LoadGroupSucceededAction(group));
} else {
store.dispatch(LoadNonMemberGroupSucceededAction(group));
}
} else {
store.dispatch(LoadGroupSucceededAction(null));
}
});
} catch (e) {
print('MW :: _loadGroups : Error: $e');
}
}
}
}, onError: (error) async {
print('MW :: _loadGroups : Error: $e');
});
} else if (action is LogoutAction) {
print('MW :: _loadGroups : Called on LogoutAction');
groupService.cancelGroupMembershipsSubscription();
}
};
}
为了防止在这种情况下引发错误,您需要在注销用户之前取消任何需要经过身份验证的用户的侦听器。 然后,当匿名登录完成后,您将为新用户重新附加侦听器。