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

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
usingMultiBlocProvider
— 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 boardStudentHomeworkBloc
for homework screenAskDoubtBloc
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
BLoC | Keep in main.dart ? | Why? |
AuthBloc | ✅ Yes | Needed everywhere |
ThemeBloc | ✅ Yes | App-wide UI state |
StudentHomeworkBloc | ❌ No | Screen-specific |
AskDoubtBloc | ❌ No | Used only when user navigates |
NotificationBloc | ✅ Yes | Background 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.
Subscribe to my newsletter
Read articles from Tarun Prajapati directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
