Blog Infos
Author
Published
Topics
, , ,
Published

So I migrated to Hilt.

It was supposed to clean up my dependency injection mess, reduce boilerplate, and make onboarding easier for the team. And to be fair, it did all that.

But then I noticed something weird:
My app’s cold start was noticeably… not cold. It was straight-up sluggish.

I checked my code.
I blamed the backend.
I restarted Android Studio (twice, just to be sure).
And then I did the one thing every dev dreads — I opened the profiler.

Turns out, Hilt was doing what it does best: initializing everything I ever told it to. Unfortunately, I was the one who told it to do way too much.

The Problem: Death by Eager Injection

Here’s what went down.

I had moved a bunch of dependencies — network clients, repositories, Room DB access, analytics loggers — into @SingletonComponent because, well, that’s what all the tutorials do.

What I didn’t realize was that Hilt would eagerly create those singletons… right at app launch. Before my splash screen animation even had a chance to flex.

Basically, my Application.onCreate() was turning into a bottleneck.

How I Fixed It (After a Brief Panic)

Once I accepted that it wasn’t Mercury retrograde or a rogue Compose recomposition, I sat down and refactored. Here’s what worked for me:

1. Use Provider<T> or @Lazy for Heavy Dependencies

If something isn’t needed immediately, don’t inject it immediately.

@Inject lateinit var heavyService: Provider<MyHeavyService>

 

This way, it only gets created when you actually call get(). No need to fire up the entire world during app launch.

2. Don’t Inject Everything into SingletonComponent

This one was a wake-up call.

I was injecting even feature-specific logic into the global scope. That meant things used only in the onboarding flow were being created at startup.

Instead, I started using:

  • ActivityRetainedComponent for ViewModels
  • ActivityComponent or FragmentComponent for screen-specific logic

Scoped things more reasonably. Cold start got faster almost immediately.

3. Delay Anything Non-Essential

Do you really need crash reporting, remote config, analytics, A/B testing, and half a dozen SDKs running in the first 0.5 seconds?

I didn’t.

So I pushed all of that into a background coroutine with a delayed initializer:

CoroutineScope(Dispatchers.Default).launch {
    Analytics.init()
    RemoteConfig.sync()
    OtherStuff.wakeUp()
}

User sees the UI instantly. Heavy stuff runs in the background. Win-win.

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

,

Solid Modularization – Untangling the dependency graph

Since we took the stage at Droidcon NYC 2019 to talk about modularization at Tinder, our team and codebase have grown a lot and so has our project and build complexity. This talk will look…
Watch Video

Solid Modularization - Untangling the dependency graph

Siggi Jonsson
Android Engineer
Tinder

Solid Modularization - Untangling the dependency graph

Siggi Jonsson
Android Engineer
Tinder

Solid Modularization - Untangling the dependency graph

Siggi Jonsson
Android Engineer
Tinder

Jobs

4. Keep Your @Provides Methods Clean

My @Provides methods had started turning into mini factories with their own business logic. Not proud of it.

So I moved complex initialization into helper classes or config builders and kept the Hilt bindings lean and predictable.

If your @Provides block takes more than a few lines or includes .build() three times… it might be doing too much.

5. Measure. Don’t Guess.

The profiler doesn’t lie.

I added log markers to track how long onCreate() was taking, and used Android Studio’s Profiler to see what was being initialized too early.

Once I had the data, the refactors became obvious — and justifiable to the team.

What I Learned
  • Hilt isn’t the problem — overusing SingletonComponent and injecting too much too soon is.
  • Delaying non-critical dependencies can drastically improve startup performance.
  • Proper scoping isn’t just good architecture — it’s also good UX.
  • Lazy injection is your friend. So is the profiler.

If you’re planning to migrate to Hilt, or already have, take this as a reminder: powerful tools need thoughtful usage.

And if your app feels slower after “cleaning up” with Hilt…
maybe it’s not your app that’s messy — maybe it’s your startup strategy.

Follow me for more Android dev lessons, real-world mistakes, and hard-won fixes that didn’t come from ChatGPT .

This article was previously published on proandroiddev.com.

Menu