Smarter State Management in Flutter: When Not to Put BLoCs in main.dart

Tarun PrajapatiTarun Prajapati
2 min read

While building a modular Flutter app using the BLoC (Business Logic Component) pattern, I stumbled upon a performance anti-pattern that many devs (including me) often fall into:

Putting all BLoCs inside main.dart using MultiBlocProvider — whether or not they are needed immediately.

At first, this feels clean and centralized. But if you're dispatching events (like ..add(FetchData())) during BLoC creation, those API calls will run the moment the app starts — even if the screen is never visited.


🤯 What This Actually Means

Let’s say you have BLoCs like:

  • StudentNoticeBloc for notice board

  • StudentHomeworkBloc for homework screen

  • AskDoubtBloc for student questions

If you do this in main.dart:

BlocProvider(
  create: (context) => StudentHomeworkBloc()..add(FetchHomework()),
),

You're telling your app:

"Run this API call immediately when the app starts, even if the user never opens the Homework screen."

Over time, this results in:

  • ❌ Wasted API calls

  • 📉 Slower startup time

  • 📦 Higher memory usage

  • 😩 Unscalable architecture

✅ A Better Way: Lazy Initialization Per Screen

For BLoCs tied to a single screen, it’s better to initialize them locally when the user navigates to that screen.

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (_) => BlocProvider(
      create: (_) => StudentHomeworkBloc()..add(FetchHomework()),
      child: HomeworkScreen(),
    ),
  ),
);

Or trigger the fetch event inside the screen’s initState():

@override
void initState() {
  super.initState();
  context.read<StudentHomeworkBloc>().add(FetchHomework());
}

This keeps your app:

  • ⚡ Fast and lean on startup

  • 🧠 Logical and modular

  • 🌱 Easy to scale as your app grows

📌 So, When Should You Use main.dart for BLoCs?

Use it only for global state that:

  • Is used across many screens

  • Needs to load at app startup

  • Represents app-wide concerns

BLoCKeep in main.dart?Why?
AuthBloc✅ YesNeeded everywhere
ThemeBloc✅ YesApp-wide UI state
StudentHomeworkBloc❌ NoScreen-specific
AskDoubtBloc❌ NoUsed only when user navigates
NotificationBloc✅ YesBackground sync across app

🧠 TL;DR

  • Don’t blindly load all BLoCs in main.dart.

  • If a screen might not be opened, don’t trigger its BLoC or API at startup.

  • Use local BlocProvider around widgets/screens to scope them better.

  • Keep global state global — keep feature logic scoped.

🤔 How Do You Handle BLoC Placement?

Do you:

  • Load all in main.dart?

  • Use a hybrid approach?

  • Combine BLoC with Riverpod, Provider, or other state management tools?

Let’s exchange notes — I’m always looking to improve my architecture.

1
Subscribe to my newsletter

Read articles from Tarun Prajapati directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Tarun Prajapati
Tarun Prajapati