how to use flutter_bloc with go_router
1,086
Solution 1
Since bloc also returns states in form of a stream, you can directly use it. You can do it like ->
refreshListenable = GoRouterRefreshStream(authenticationBloc.stream),
Solution 2
For me, Mixing changeNotifier with the Bloc class and calling notififyListener() from the event worked
This is my bloc class
class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState>
with ChangeNotifier {
AuthenticationBloc(
{required AuthenticationRepository authenticationRepository})
: _authenticationRepository = authenticationRepository,
super(const AuthenticationState.unknown()) {
on<AppStarted>(_onAppStarted);
on<AuthenticationUserChanged>(_onAuthenticationUserChanged);
on<AuthenticationLogoutRequested>(_onAuthenticationLogoutRequested);
_userSubscription = _authenticationRepository.user
.listen((user) => add(AuthenticationUserChanged(user)));
}
final AuthenticationRepository _authenticationRepository;
late StreamSubscription<User> _userSubscription;
@override
Future<void> close() {
_userSubscription.cancel();
return super.close();
}
FutureOr<void> _onAppStarted(
AppStarted event, Emitter<AuthenticationState> emit) {
emit(AuthenticationState.unknown());
}
FutureOr<void> _onAuthenticationUserChanged(
AuthenticationUserChanged event, Emitter<AuthenticationState> emit) {
final status = event.user != User.empty
? AuthenticationState.authenticated(event.user)
: const AuthenticationState.unauthenticated();
emit(status);
notifyListeners();
}
FutureOr<void> _onAuthenticationLogoutRequested(
AuthenticationLogoutRequested event, Emitter<AuthenticationState> emit) {
unawaited(_authenticationRepository.logOut());
}
}
This is GoRouter
GoRouter routes(AuthenticationBloc bloc) {
return GoRouter(
routes: [
GoRoute(
path: '/',
name: 'home',
builder: (context, state) => const HomePage(),
),
GoRoute(
path: '/login',
name: 'login',
builder: (context, state) => const LoginPage(),
),
],
redirect: (state) {
final isLoggedIn =
bloc.state.status == AuthenticationStatus.authenticated;
final isLoggingIn = state.location == '/login';
print(isLoggedIn);
if (!isLoggedIn && !isLoggingIn) return '/login';
if (isLoggedIn && isLoggingIn) return '/';
return null;
},
refreshListenable: bloc);
}
Solution 3
Maybe you can do something like this:
class AuthStateNotifier extends ChangeNotifier {
late final StreamSubscription<AuthState> _blocStream;
AuthStateProvider(AuthBloc bloc) {
_blocStream = bloc.stream.listen((event) {
notifyListeners();
});
}
@override
void dispose() {
_blocStream.cancel();
super.dispose();
}
}
The code is from this answer, hope you get the idea.
Author by
ismailfarisi
Updated on January 02, 2023Comments
-
ismailfarisi over 1 year
I have built an app where I use flutter_bloc. i want to use go_router for navigation.but for dynamic routing how can i use GoRouter refreshListener parameter with flutter_bloc
GoRouter( routes: [ GoRoute( path: '/', name: 'home', pageBuilder: (context, state) => HomePage.page(), ), GoRoute( path: '/login', name: 'login', pageBuilder: (context, state) => LoginPage.page(), ), ], redirect: (state) { final isLoggedIn = bloc.state.status == AuthenticationStatus.authenticated; final isLoggingIn = state.location == '/login'; if (!isLoggingIn && !isLoggingIn) return '/login'; if (isLoggedIn && isLoggingIn) return "/"; return null; }, refreshListenable: );
-
ismailfarisi over 2 yearsthanks for the answer. but I found it easier to mixin changenotifier with bloc class and notifylistener() for the particular event, in this case change in authstate
-
聂超群 over 2 years
minxin
solution sounds easier :) -
EngineSense about 2 yearsreally nice find...