After much reading, I want to share my solution, I hope it can help many people. :)
- I create a file called go_router_refresh_stream.dart within my project that looks like this:
import 'dart:async';
import 'package:flutter/foundation.dart';
class GoRouterRefreshStream extends ChangeNotifier {
GoRouterRefreshStream(Stream<dynamic> stream) {
notifyListeners();
_subscription = stream.asBroadcastStream().listen(
(dynamic _) => notifyListeners(),
);
}
late final StreamSubscription<dynamic> _subscription;
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
}
- With the help of getIt, I make a registerLazySingleton of my AuthBloc.
getIt.registerLazySingleton(
() => AuthBloc(
authStatusChangesFirebaseUseCase: getIt(),
authCurrentUserUseCase: getIt(),
),
);
- I have a mixin of my GoRoute() class and with the help of getIt, I access the stream property of my AuthBloc.
Mixin GoRoute():
mixin RouterMixin on State<MyApp> {
final _router = GoRouter(
initialLocation: LoginScreen.path,
errorBuilder: (context, state) => ErrorScreen(routerState: state),
routes: [
GoRoute(
name: LoginScreen.name,
path: LoginScreen.path,
builder: (context, state) => const LoginScreen(),
),
GoRoute(
path: HomeScreen.path,
name: HomeScreen.name,
builder: (context, state) => HomeScreen(),
),
],
redirect: (context, state) async {
final sessionStatus = context.read<AuthBloc>().state.status;
if (sessionStatus == AuthStatus.unauthenticated) {
return LoginScreen.path;
}
return null;
},
refreshListenable: GoRouterRefreshStream(GetIt.instance<AuthBloc>().stream),
);
GoRouter get router => _router;
}
- Lastly, I convert my MyApp class into a StatefulWidget so that I can use the mixin and also instantiate my BlocProvider:
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with RouterMixin {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => getIt<AuthBloc>(),
child: MaterialApp.router(
title: 'Dase BackOffice',
theme: DaseTheme.lightTheme,
darkTheme: DaseTheme.darkTheme,
themeMode: ThemeMode.dark,
routerConfig: router,
),
);
}
}
The route protection works perfectly. The use of getIt with flutter_bloc is completely a personal preference.
pd: I don't publish the logic of my AuthBloc for practical reasons, but if you're interested, I can tell you that it's a copy of the example called Firebase Login found in the official flutter_bloc documentation :P
Saludos