所以我将提供我的代码,因为它是理解我的问题的最简单的方法。我从我的UserService类开始,它创建一个流,每当AuthStateChanges(来自FirebaseAuth)流触发时,该流就会连续接收数据
enum AuthEventEnum { authenticated, unauthenticated }
class UserService {
StreamController<AuthEventEnum> controller =
StreamController<AuthEventEnum>();
late final StreamSubscription _subscription;
StreamSubscription get subscription => _subscription;
UserService() {
final StreamSubscription _subscription =
FirebaseAuth.instance.authStateChanges().listen(
(User? user) {
print(user);
if (user == null) {
controller.sink.add(AuthEventEnum.unauthenticated);
} else if (user != null) {
controller.sink.add(AuthEventEnum.authenticated);
}
},
);
}
}
现在我试着连接到我的AuthBloc(我很确定错误来自这里...但我不知道如何修复它)
class AuthBloc extends Bloc<AuthEventEnum, AuthState> {
final UserService _userService;
late final _addEvents;
AuthBloc(this._userService) : super(AuthInitial()) {
_addEvents = _userService.controller.stream.listen(
(event) {
if (event == AuthEventEnum.authenticated) {
mapEventToState(AuthEventEnum.authenticated);
} else if (event == AuthEventEnum.unauthenticated) {
mapEventToState(AuthEventEnum.authenticated);
}
},
);
}
@override
Stream<AuthState> mapEventToState(AuthEventEnum event) async* {
if (event == AuthEventEnum.authenticated) {
yield AuthAuthenticatedState();
} else if (event == AuthEventEnum.unauthenticated) {
yield AuthUnauthenticatedState();
}
}
}
现在的最终目标是根据他们的AuthStatus将用户重定向到不同的路由…
class AppRouter {
AuthBloc authBloc;
late final GoRouter routes;
AppRouter({required this.authBloc}) {
routes = GoRouter(
initialLocation: '/home',
redirect: (context, state) {
if (authBloc.state is AuthInitial) {
return '/register';
} else if (authBloc.state is AuthAuthenticatedState) {
return '/app';
} else if (authBloc.state is AuthUnauthenticatedState) {
return '/register';
}
},
routes: [
GoRoute(
path: '/home',
builder: (context, state) => const HomePage(),
),
GoRoute(
path: '/login',
builder: (context, state) => const LoginPage(),
),
GoRoute(
path: '/register',
builder: (context, state) => const RegisterPage(),
),
GoRoute(
path: '/app',
builder: (context, state) => const AppPage(),
),
],
);
}
}
在主函数相关情况下,其为:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
final authService = UserService();
final authBloc = AuthBloc(authService);
runApp(
BlocProvider.value(
value: authBloc,
child: MaterialApp.router(
title: 'flutter demo',
theme: ThemeData(primarySwatch: Colors.blue),
routerConfig: AppRouter(authBloc: authBloc).routes,
),
),
);
}
了解有关Bloc如何处理流以及Bloc如何侦听其他流并向自身添加事件的详细信息
1条答案
按热度按时间jhdbpxl91#
对于初学者来说,你正在使用一个非常过时的Bloc API。@ Krish Bhanushali在评论中链接的文章是一个良好的开端。没有理由继续使用
mapEventToState
,您应该更新您的Bloc包。除此之外,直接使用Bloc处理流的最佳方式是
emit.forEach(...)
然后在初始化BlocProvider时调用该事件。
所以这里的总体思路是使用Bloc提供的工具来处理流。Firebase已经提供了一个
Stream<User>
,所以只需要使用它。无需创建额外的流/控制器/订阅等。它更简单,更不容易出错。