IncorrectMouse
IncorrectMouse

Reputation: 229

Flutter auto_route | How do I wrap a route with BlocProvider?

So, I'm using the auto_route package for navigation in my app and flutter_bloc for state management. When I was using the old Navigator, I could just wrap a route with a BlocProvider. For example:

class Router {
  static Route<dynamic> generateRoute(RouteSettings settings) {
    switch (settings.name) {
      case '/':
        return MaterialPageRoute(
          builder: (_) => BlocProvider( // wrapped Home with BlocProvider
            create: (context) => SubjectBloc(),
            child: Home(),
          ),
        );
      case '/feed':
        return MaterialPageRoute(builder: (_) => Feed());
    }
  }
}

Now, auto_route uses annotations to generate a routing file. How would I go around providing provider context to the route?

Upvotes: 7

Views: 13462

Answers (3)

Andres
Andres

Reputation: 41

You can also use a custom route builder.

Route<T> myCustomRouteBuilder<T>(BuildContext context, Widget child, CustomPage<T> page){            
  return PageRouteBuilder(            
    fullscreenDialog: page.fullscreenDialog,            
    // this is important            
    settings: page,            
    pageBuilder: (,__,___) => BlocProvider( // wrapped page with BlocProvider
      create: (context) => SubjectBloc(),
      child: child,
    ),
  );            
}

@AutoRoute(
  replaceInRouteName: 'Page,Route',
  routes: [
    // ...
    CustomRoute(
      path: '/'
      page: FeedPage
      // ...
      customRouteBuilder: myCustomRouteBuilder,
      // ...
    ),
    // ...
  ]
)

where FeedPage is your the Feed widget. Each page in auto_route should have a pre-defined suffix in its name as you probably already know.

Upvotes: 2

mrgnhnt96
mrgnhnt96

Reputation: 3945

The answer depends on how your routes are constructed, I'll show you how I achieve this.

For nested routes (When you provide children to your routes), you can use a wrapper. You can wrap your bloc provider(s) around the child and it will provide the bloc to all children screens.

/// routes

AutoRoute(
    page: SupportWrapper,
    name: 'SupportRouter',
    path: 'support',
    children: [
        AutoRoute(
            page: HelpSupportScreen,
            path: '',
        ),
        AutoRoute(
            page: MessageUsScreen,
            path: 'issue',
        ),
    ],
),
/// build method of [support_wrapper.dart]

@override
Widget build(BuildContext context) {
  return MultiBlocProvider(
    providers: [
      BlocProvider(
        create: (context) => _supportCubit,
      ),
    ],
    child: const AutoRouter(),
  );
}

If you are not using a wrapper widget, e.g. its a single screen with no children routes, I would create a separate widget to wrap the BlocProvider around the screen.

class SupportScreen extends StatelessWidget {
  const SupportScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => _supportCubit
      child: const _SupportScreen(),
    );
  }
}

class _SupportScreen extends StatelessWidget {
  const _SupportScreen({Key? key}) : super(key: key);

// rest of your screens code...

Upvotes: 7

IncorrectMouse
IncorrectMouse

Reputation: 229

We have our page widget (state/less/ful) implement AutoRouteWrapper

class HomePage extends StatelessWidget implements AutoRouteWrapper{
  .....
 @override
 Widget wrappedRoute(context){
   return BlocProvider(
            create: (context) => HomeBloc(),
            child:  this, // this as the child Important!
          );
   }

}

Upvotes: 8

Related Questions