如何更新AuthBloc状态中AuthState.authenticated存储的用户数据?
认证Bloc用户数据更新解决方案
核心原因
Bloc默认内置状态去重逻辑,连续两次yield的状态如果通过==判定相等,就不会向监听方下发新状态。使用临时状态加延迟的方式属于非常规hack,不符合Bloc的设计规范,且稳定性差。
可落地解决方案
方案1:新增专属用户信息更新事件(最推荐,语义清晰)
不要复用原本用于登录态校验的AuthCheckRequested,新增单独的用户信息更新事件,逻辑更直观:
- 新增事件定义
part of 'auth_bloc.dart'; @freezed class AuthEvent with _$AuthEvent { const factory AuthEvent.authCheckRequested() = AuthCheckRequested; const factory AuthEvent.signedOut() = SignedOut; // 新增事件,携带更新后的用户数据 const factory AuthEvent.userProfileUpdated(User user) = UserProfileUpdated; }
- 新增事件处理逻辑
@override Stream<AuthState> mapEventToState( AuthEvent event, ) async* { yield* event.map( authCheckRequested: (e) async* { final userOption = await _authFacade.getSignedInUser(); yield userOption.fold( () => const AuthState.unauthenticated(), (user) => AuthState.authenticated(user), ); }, signedOut: (e) async* { await _authFacade.signOut(); yield const AuthState.unauthenticated(); }, // 新增更新逻辑 userProfileUpdated: (e) async* { yield state.maybeMap( authenticated: (_) => AuthState.authenticated(e.user), orElse: () => state, ); }, ); }
用户数据更新后,直接向AuthBloc提交AuthEvent.userProfileUpdated(更新后的User实例)即可触发状态刷新,不需要中间状态或延迟。
方案2:修正数据类相等判断逻辑
如果是因为AuthState或User类没有正确实现==和hashCode,导致即使用户数据变更,新旧状态仍被判定为相等,修正相等判断逻辑即可:
- 若使用Equatable基类,确保所有可变属性都加入props数组:
class AuthState extends Equatable { const AuthState.authenticated(this.user); final User user; @override List<Object?> get props => [user]; } class User extends Equatable { const User({required this.id, required this.nickname, required this.avatar}); final String id; final String nickname; final String avatar; @override List<Object?> get props => [id, nickname, avatar]; }
- 若使用Freezed生成数据类,默认已经实现了正确的深相等判断,只要用户数据有变更,新旧状态就会被识别为不同,直接重发
AuthCheckRequested即可触发更新。
方案3:关闭Bloc状态去重(适用需要强制刷新的场景)
如果业务确实需要支持下发相同状态触发刷新,可以直接关闭当前Bloc的状态去重逻辑:
- Bloc 8.0+版本写法:
class AuthBloc extends Bloc<AuthEvent, AuthState> { AuthBloc() : super(const AuthState.initial()) { on<AuthEvent>( (event, emit) => mapEventToState(event).listen(emit), // 关闭默认的状态去重 transformer: (events, mapper) => events.asyncExpand(mapper), ); } }
- 旧版本Bloc写法:
@override Stream<Transition<AuthEvent, AuthState>> transformStates( Stream<Transition<AuthEvent, AuthState>> transitions, ) { return transitions; }
该方案不需要调整现有业务逻辑,缺点是会失去状态去重带来的性能优化。
内容的提问来源于stack exchange,提问作者w461
相关产品推荐
相关产品推荐

