Flutter BLoC Tutorial

Let's learn how to use BLoC efficiently. We will cover the complex ideas about BLoC and how to use them. Some of the BLoC concepts I have covered in BLoc Gym App.

RepositoryProvider

You use RepositoryProvider to load data from network, making http request or connecting to cloud messaging and feed the data to BLoC. For this reason first you need to wrap your app in the root level using RepositoryProvider and create repository using your repository class.

In general  the child of the RepositoryProvider is a BlocProvider

RepositoryProvider provides the repository to its children through RepositoryProvider.of(context). When developers create a new RepositoryProvider and that gets available to the rest of the subtree.

BlocProvider

Just RepositoryProvider, BLocProvider also takes a BLoC(a class that has events and states) and creates BLoC out of it(I know it's confusing).

BlocProvider provides the bloc to its children through BlocProvider.of(context). In most cases, developers create a new BlocProvider and that gets available to the rest of the subtree.

If you have the video you know that, 

  1. RepositoryProvider needs a repository class
  2. RepositoryProvider needs BlocProvider as a child
  3. BlocProvider needs instance of RepositoryProvider
  4. BlocProvider needs a bloc
  5. Bloc needs events and states

BLoC List of Providers

Let's see how to work with this.

If you have BlocProviders are in a seperate class and inside a List, 

  static List<PageEntity> Routes(){
    return [
      PageEntity(
          path:AppRoutes.INITIAL,
          page:Welcome(),
          bloc:BlocProvider(create: (_) => WelcomeBloc())
      ),
      PageEntity(
          path:AppRoutes.Sign_in,
          page:SignIn(),
          bloc:BlocProvider(create: (_) => SignInBloc())
      ),
      PageEntity(
          path:AppRoutes.Register,
          page:Register(),
          bloc:BlocProvider(create: (_) => RegisterBloc())
      ),
      PageEntity(
          path:AppRoutes.Forget,
          page:Forget(),
          bloc:BlocProvider(create: (_) => ForgetBloc())
      ),
      PageEntity(
        path:AppRoutes.Application,
        page:Application(),
        bloc:BlocProvider(create: (_) => ApplicationBloc())
      ),
      PageEntity(
          path:AppRoutes.Home,
          page:Home(),
          bloc:BlocProvider(create: (_) => HomeBloc())
      ),
      PageEntity(
          path:AppRoutes.Course,
          page:Course(),
          bloc:BlocProvider(create: (_) => CourseBloc())
      ),
      PageEntity(
          path:AppRoutes.Contibitor,
          page:Contibitor(),
          bloc:BlocProvider(create: (_) => ContibitorBloc())
      ),
      PageEntity(
          path:AppRoutes.CourseDetail,
          page:CourseDetail(),
          bloc:BlocProvider(create: (_) => CourseDetailBloc())
      ),
      PageEntity(
          path:AppRoutes.Lesson,
          page:Lesson(),
          bloc:BlocProvider(create: (_) => LessonBloc())
      ),
      PageEntity(
          path:AppRoutes.Message,
          page:Message(),
          bloc:BlocProvider(create: (_) => MessageBloc())
      ),
      PageEntity(
          path:AppRoutes.Chat,
          page:Chat(),
          bloc:BlocProvider(create: (_) => ChatBloc())
      ),
      PageEntity(
          path:AppRoutes.Photoview,
          page:PhotoView(),
          bloc:BlocProvider(create: (_) => PhotoViewBloc())
      ),
      PageEntity(
          path:AppRoutes.VideoCall,
          page:VideoCall(),
          bloc:BlocProvider(create: (_) => VideoCallBloc())
      ),
      PageEntity(
          path:AppRoutes.VoiceCall,
          page:VoiceCall(),
          bloc:BlocProvider(create: (_) => VoiceCallBloc())
      ),
      PageEntity(
          path:AppRoutes.Unotification,
          page:Unotification(),
          bloc:BlocProvider(create: (_) => UnotificationBloc())
      ),
      PageEntity(
          path:AppRoutes.Profile,
          page:Profile(),
          bloc:BlocProvider(create: (_) => ProfileBloc())
      ),
      PageEntity(
          path:AppRoutes.Account,
          page:Account(),
          bloc:BlocProvider(create: (_) => AccountBloc())
      ),
      PageEntity(
          path:AppRoutes.Setting,
          page:Setting(),
          bloc:BlocProvider(create: (_) => SettingBloc())
      ),
      PageEntity(
          path:AppRoutes.Search,
          page:Search(),
          bloc:BlocProvider(create: (_) => SearchBloc())
      ),
    ];
  }

See how we created a lot of routes like Getx and injected our BlocProvider. So above Routes() function returns a list of Routes with certain BLoC.

Then we created a new List in the below function and return 

  static List<dynamic> Blocer(BuildContext context){
    List<dynamic> blocerList = <dynamic>[];
    for(var blocer in Routes()){
      blocerList.add(blocer.bloc);
    }
    return blocerList;
  }

The returned Blocs could be injected inside MultiBlocProvider

MultiBlocProvider(
        providers: [...AppPages.Blocer(context)],
        child: ScreenUtilInit(
            designSize: Size(375, 812),
            builder: (context, child) => MaterialApp(
              title: 'ulearning',
              theme: AppTheme.light,
              debugShowCheckedModeBanner: false,
              navigatorObservers: [AppPages.observer],
              initialRoute: AppRoutes.INITIAL,
              onGenerateRoute: AppPages.GenerateRouteSettings,
            ))
    );

AppPages.Blocer(context), inject all the BlocProvider inside MuliBlocProvider.

BLoC Routing

BLoC could also be used for routing. But one may disagree that, we must use BLoC for seperating the business logic from UI. 

Personally I think it's not gonna hurt the performance and add extra code in your lib. On the other hand, if you use a plugin to do it, you will have a lot of extra code. And version control is also a problem. In face there are not good routing plugins out there apart from go_router and Getx routing. 

Some people don't wanna use Getx and go_routing is not complete yet. So I dedcided to go ahead with on BLoC routing.

The steps we followed to do this

  1. created BLoC for each screen (with event and state)
  2. created a class model as a wrapper for BLoC routing
  3. created a List of objects in a static method(return the model at the top)
  4. created another function to return List of BLoCs and use in the MultiBlocProvider
  5. created a call back function to detect which route has been tapped from the UI

 

......coming more.....

 

Recent posts