0% found this document useful (0 votes)
5 views18 pages

Mastering Android Dependency Injection

desc
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views18 pages

Mastering Android Dependency Injection

desc
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Mastering Android

Dependency
Injection – 2025
Interview Edition
🧪 Hilt • Koin • Manual DI • Testing • Scoping
🧱 Modular Architecture
💉 Constructor Injection
⚙️ Lifecycle Scopes
🔄 ViewModel Integration
Elevate code quality and maintainability with DI
techniques used across modern Android apps,
scalable fintech platforms, and enterprise-grade
architectures
Q1. What is Dependency 1/16

Injection (DI)? Why do we use


it?
A:
Dependency Injection is a design pattern where objects
receive their dependencies from external sources rather
than creating them internally.

Benefits:
Loose coupling between classes
Easier unit testing (can inject mocks)
Promotes modularity and clean architecture
Reusability and flexibility in app design
Better testability - isolate classes during testing
Follows SOLID principles (Dependency Inversion)

Quick example: Instead of UserRepository creating its own


ApiService, the DI framework injects it via constructor
using @Inject.
2/16

Q2. What are the types of DI?

A:

1. Constructor Injection – Preferred in most cases

(dependencies passed in the constructor) ✅


Immutable dependencies, fail-fast if missing

2. Field Injection – Injects directly into class fields (used

with @Inject annotations in Hilt/Dagger) ⚠️ Can't use


dependencies in constructor

3. Method Injection – Dependencies passed via method

calls (rare in Android, used for optional dependencies)

Best Practice: Use Constructor Injection for required


dependencies, Field Injection only when constructor
injection isn't possible (like Activities/Fragments).
Q3. What are the common 3/16

DI frameworks used in
Android?
A:

Hilt (Google-supported) - Current recommendation, built

on Dagger

Koin (Kotlin-native, DSL-based) - Lightweight, easy setup

Dagger (compile-time, feature-rich) - Enterprise apps,

complex graphs

Manual DI (no library) - Small projects, learning

When to choose:

Hilt: New projects, Jetpack integration needed

Koin: Kotlin-first teams, quick prototypes

Dagger: Large apps, performance critical

Manual: Simple apps, educational purposes


Q4. What is Hilt and why 4/16

should we use it?


A:
Hilt is Google's recommended dependency injection library
built on top of Dagger. It simplifies setup and integrates
seamlessly with Android Jetpack libraries.

Key Advantages:
Less boilerplate - Reduces Dagger's complexity by 70%
Lifecycle-aware scoping - Automatic cleanup with Android
components
Easy ViewModel injection - Built-in support with
@HiltViewModel
Better tooling and testing - IDE support, simplified test
setup
Jetpack integration - WorkManager, Navigation, Compose
ready
Compile-time safety - Catches DI errors at build time, not
runtime

Why choose Hilt: Google's current standard for new Android


projects, active development, and extensive
documentation.
Q5. Key annotations used in 5/16
Hilt?
A:
Setup:
@HiltAndroidApp – Entry point in Application class
@AndroidEntryPoint – Annotate Activities, Fragments,
Services, etc.
Injection:
@Inject – Inject constructor or field
@HiltViewModel – For ViewModel injection with lifecycle
awareness
Dependency Provision:
@Module and @InstallIn – Provide dependencies to
specific components
@Provides – Used inside modules to supply complex
objects
@Binds – Bind interface to implementation (more efficient
than @Provides)
Scoping:
@Singleton, @ActivityScoped, @FragmentScoped –
Control instance lifecycle
6/16

Q6. How do you inject


dependencies in a
ViewModel using Hilt?

A:
Use @HiltViewModel and constructor injection to let Hilt
provide the dependencies:

Then, inside a Composable:


val viewModel: MyViewModel = hiltViewModel()
7/16

Q7. What are Hilt scopes?

A:

@Singleton – Single instance for entire app

@ActivityRetainedScoped – Retained across config

changes

@ViewModelScoped – One per ViewModel instance

@ActivityScoped, @FragmentScoped – Per lifecycle of

component
Q8. How to test with Hilt? 8/16

A:
Setup:
Use @HiltAndroidTest on test classes
Use HiltTestRule for proper initialisation
Override Dependencies:
Use @UninstallModules to remove production modules
Create test modules with @TestInstallIn to provide
mocks/fakes
Alternative: Use @BindValue for simple replacements
Key Benefits:
Replace real APIs with mock implementations
Inject test doubles without changing production code
Maintain proper scoping in the test environment

Example use case: Replace NetworkRepository with


FakeRepository to test offline scenarios without network
calls.
Q9. What is Koin? 9/16

A:
Koin is a Kotlin-native dependency injection framework using a
DSL instead of annotations. It's lightweight, uses runtime
resolution, and requires no code generation.

Key Characteristics:
Pure Kotlin - No Java interop, idiomatic Kotlin code
Runtime DI - Dependencies resolved at runtime, not
compile-time
DSL-based - Declarative syntax with module { }, single { },
factory { }
No code generation - Faster build times, simpler debugging
Lightweight - Minimal setup, quick to learn

When to choose Koin:


Kotlin-first projects with small to medium complexity
Rapid prototyping and quick setup are needed
Teams preferring runtime flexibility over compile-time
safety
Projects where build time is more critical than runtime
performance
10/16
Q10. Core Koin components?
A:

Declaration:

module { } – Declare DI container with dependencies

single { } – Singleton provider (one instance app-wide)

factory { } – Creates a new instance every time requested

scoped { } – Instance tied to scope lifecycle

Retrieval:

get() – Direct dependency retrieval

by inject() – Lazy property delegation

inject() – Lazy injection (alternative syntax to by inject())

Advanced:

bind<Interface>() – Bind implementation to interface

named("qualifier") – Distinguish between same-type

dependencies
Q11. How to define and start 11/16

Koin?
A:
Setup Process:
Define modules - Create modules with single{} for
singletons or factory{} for new instances
Start Koin in Application - Use startKoin{} with
androidContext() and modules()
Inject dependencies - Use get() for direct retrieval or by
inject() for lazy injection

Key Points:
Modules define your dependency graph
startKoin{} initialises the DI container in the Application
class
Pass Android context and module list to make
dependencies available app-wide
Once started, dependencies are accessible via get() or
inject() throughout the app
Q12. How to inject ViewModel 12/16
in Koin?
A:

Step 1: Define in Module

Use viewModel{} DSL specifically designed for

ViewModel injection

Koin handles ViewModel lifecycle automatically

Constructor dependencies are resolved automatically

Step 2: Inject in Activity/Fragment

Use by viewModel() delegate for lazy injection

Use getViewModel() for immediate retrieval

Koin provides proper ViewModel scope

(Activity/Fragment lifecycle)

Key Benefits:

Automatic lifecycle management - no manual cleanup

needed

Constructor injection works seamlessly

Scoped to Activity/Fragment automatically


13/16
Q13. Difference between
single, factory, and scoped?

These are Koin's lifecycle definitions for how dependencies


are provided:
single: Creates one shared instance for the entire app.
It behaves like a singleton. Best used for classes like
repositories, database clients, or network handlers.
factory: Creates a new instance every time the
dependency is requested. Use this for stateless or
short-lived objects.
scoped: Ties the instance to a specific Koin scope,
such as an Activity or Fragment. The object will exist
only as long as the scope is alive.
✅ Summary:
Use single for long-lived shared objects
Use factory when you always need a fresh instance
Use scoped when the object lifecycle should match a
UI component or screen
14/16
Q14. Koin vs Hilt Comparison
A:

Koin and Hilt are both popular dependency injection


frameworks used in Android, but they differ in key ways:

Koin is a runtime DI framework written in pure Kotlin. It


uses a DSL for declaring dependencies and requires no
code generation. It's easy to learn and quick to set up,
but has slightly lower performance due to runtime
resolution.

Hilt is built on top of Dagger, which uses compile-time


DI. It relies on annotations and generates code at build
time, making it more efficient and scalable for large
apps. It integrates tightly with Jetpack libraries and
supports advanced scoping.

✅ In short:
Use Koin for quick setups, prototypes, or small/medium
apps
Use Hilt for production apps, complex architectures, or
when you want Jetpack integration and compile-time
safety
15/16

Q15. Testing in Koin?


A:
Koin makes testing easy by allowing you to replace
production dependencies with mocks or fakes using
declare() or declareMock().

You can either:


Define separate test modules
Or override real dependencies directly in the test
scope

Example (verbal form):

You can replace MyRepository with a FakeRepository


during tests using declare { single<MyRepository> {
FakeRepository() } }.
This ensures your tests use isolated and controlled
dependencies without changing the production code.

✅ This approach keeps tests clean, fast, and


independent of real implementations.
16/16

🔹 Bonus: When to use Manual


DI?

A:
Manual Dependency Injection can be a good choice when:

✅ The project is very small or simple, and introducing a


DI framework is overkill
✅ You want to avoid the overhead of setup and build-
time processing
✅ You need full control over object creation and
lifecycle without relying on external libraries
✅ You’re in a learning environment, debugging core
concepts, or building a prototype

🧠 Manual DI is simple but not scalable — it’s ideal when


clarity and minimalism outweigh flexibility and
automation.
Thank You for Reading!

Ready to dive deeper into Android, Kotlin, and


Clean Architecture?

I regularly share hands-on tutorials and


practical code tips that you can apply directly
to your projects.

Got questions or want to see specific topics


covered? Drop a comment below or send me
a DM - I'd love to hear what you're working on!

You might also like