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.

Share:
1,086
ismailfarisi
Author by

ismailfarisi

Updated on January 02, 2023

Comments

  • ismailfarisi
    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
    ismailfarisi over 2 years
    thanks 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
    EngineSense about 2 years
    really nice find...