How to Migrate a Flutter Application from GetIt to Bloc (Without Losing Your Code)

migrate GetIt to Bloc

If you’re here, you’re probably searching something like:

“How to migrate GetIt to Bloc?”
“Is it worth moving from GetIt to Bloc?”
“Should I refactor my existing Flutter app to Bloc?”

Trust me — I searched the same things.

My first Flutter project wasn’t big. I built it fast using GetIt because dependency injection felt clean and effortless. But as the project grew, something changed — the state became harder to track, debugging felt unpredictable, and suddenly my widget tree held too much logic.

That’s when I knew it was time to migrate GetIt to Bloc.

This guide is everything I wish I knew before starting the migration.

🧭 Why Migrate GetIt to Bloc?

Before you start refactoring, you should ask:

Why do I want to migrate GetIt to Bloc?

For me — the answer was:

  • I needed predictable state behavior

  • I wanted clearer event → state → UI flow

  • I needed better scalability and testing

  • Multiple screens were sharing state and things felt messy

🚦 When Bloc Makes Sense

👍 You should migrate if:

  • The project is growing or becoming long-term

  • Multiple screens need shared state

  • You want cleaner business logic separation

  • You need robust unit testing

👎 You should NOT migrate if:

  • The app is small and static

  • No shared/global state exists

  • GetIt already works perfectly for your use case

Migration should solve a problem — not create one.

Step 1 — Identify What GetIt Manages

Before removing anything, list what GetIt currently handles.

For example, in one of my projects, I had:

- ThemeService
- AuthService
- ApiClient
- UserPreferences
- CartService

GetIt makes it easy to write this:

final locator = GetIt.instance;

void setupLocator() {
  locator.registerSingleton<ThemeService>(ThemeService());
}

But the problem?
Services contain logic, and widgets eventually rely on them directly. Which means UI + logic blend together — and that’s not ideal long-term.

Step 2 — Choose Which Feature to Convert First

Don’t migrate the entire app at once.

Start with something simple — like theme switching.

Why theme?
Because it:

  • touches the UI

  • requires state sharing

  • is easy to test

This will help you validate the flow before migrating more complex features like authentication.

Instead of throwing everything into one giant Bloc, break things down:

  • AuthBloc

  • ThemeBloc

  • UserBloc

  • SettingsBloc

Each Bloc handles one responsibility.
Bloc embraces the Single Responsibility Principle — something GetIt doesn’t enforce.

Step 3 — Before & After (GetIt → Bloc)

 

 

Let’s look at a real example.

🧵 Before: Using GetIt + setState

final themeService = GetIt.instance<ThemeService>();

class SettingsPage extends StatefulWidget {
  @override
  _SettingsPageState createState() => _SettingsPageState();
}

class _SettingsPageState extends State<SettingsPage> {
  bool isDark = themeService.isDarkMode;

  void toggleTheme() {
    themeService.toggleTheme();
    setState(() {
      isDark = themeService.isDarkMode;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Switch(value: isDark, onChanged: (_) => toggleTheme());
  }
}

Notice how:

  • UI triggers business logic

  • Service updates state

  • UI updates manually

After: Using Bloc

We first create a Bloc:

class ThemeEvent {}

class ToggleThemeEvent extends ThemeEvent {}

class ThemeState {
  final bool isDark;
  ThemeState(this.isDark);
}

class ThemeBloc extends Bloc<ThemeEvent, ThemeState> {
  final ThemeService themeService;

  ThemeBloc(this.themeService) : super(ThemeState(themeService.isDarkMode)) {
    on<ToggleThemeEvent>((event, emit) {
      themeService.toggleTheme();
      emit(ThemeState(themeService.isDarkMode));
    });
  }
}

Now the UI becomes clean and reactive:

BlocBuilder<ThemeBloc, ThemeState>(
  builder: (context, state) {
    return Switch(
      value: state.isDark,
      onChanged: (_) => context.read<ThemeBloc>().add(ToggleThemeEvent()),
    );
  },
);

No more setState().
No direct service call in widgets.
UI reacts automatically.

This is what migrating GetIt to Bloc feels like — structured, predictable, and scalable.

Step 4 — Inject Blocs at the App Level

We now use MultiBlocProvider:

void main() {
  setupLocator();

  runApp(
    MultiBlocProvider(
      providers: [
        BlocProvider(
          create: (_) => ThemeBloc(locator<ThemeService>()),
        ),
      ],
      child: const MyApp(),
    ),
  );
}

At this stage, GetIt still exists — and that’s okay.
Migration happens feature-by-feature.

Step 5 — Slowly Remove GetIt (When Ready)

Once all features move to Bloc, you can decide:

  • Keep GetIt ONLY for dependency injection
    or

  • Remove GetIt entirely if Bloc + Repository pattern feels enough

In my case, removing GetIt fully made the project feel clean — but this depends on your architecture preferences.

💡 Common Mistakes

Mistake Fix
Migrating everything at once Do it feature by feature
Keeping logic in widgets Move to Bloc
One giant Bloc managing everything Create multiple feature Blocs
Not writing tests Bloc makes testing easy — use it

🎯 Final Thoughts

Migrating a Flutter app is not just moving code — it’s improving how the app thinks and behaves.

If you’re ready to scale, test, and build long-term maintainable apps, then migrating GetIt to Bloc is one of the best decisions you’ll make as a Flutter developer.

And when you finally delete that last GetIt.instance, trust me…
you’ll feel like you just cleaned your entire room at 2 AM while listening to nostalgic songs. 😅✨

Want to learn Flutter Course, Javascript, or React Js CourseFrontend Development CourseFull Stack Development Course and More, Visit Our Website www.kaashivinfotech.com.

Related Reads:

Previous Article

Python vs JavaScript in 2025: Which Language Should You Bet Your Career On? 🚀

Next Article

6 Things You Must Know About What Is API in Java -With a SOAP API Example That Finally Made It Click 

Write a Comment

Leave a Comment

Your email address will not be published. Required fields are marked *

Subscribe to our Newsletter

Subscribe to our email newsletter to get the latest posts delivered right to your email.
Pure inspiration, zero spam ✨