0% found this document useful (0 votes)
26 views49 pages

Android Hilt-1

The document discusses Dependency Injection (DI) with a focus on Hilt, highlighting its importance for code reusability, loosely-coupled dependencies, and ease of testing. It explains how DI allows for better management of dependencies in applications and provides a quick start guide for implementing Hilt in Android projects. The document emphasizes that Hilt is the recommended DI solution by Jetpack, designed to reduce boilerplate code and simplify dependency management.

Uploaded by

Arbaz Pirwani
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)
26 views49 pages

Android Hilt-1

The document discusses Dependency Injection (DI) with a focus on Hilt, highlighting its importance for code reusability, loosely-coupled dependencies, and ease of testing. It explains how DI allows for better management of dependencies in applications and provides a quick start guide for implementing Hilt in Android projects. The document emphasizes that Hilt is the recommended DI solution by Jetpack, designed to reduce boilerplate code and simplify dependency management.

Uploaded by

Arbaz Pirwani
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
You are on page 1/ 49

Dependency Injection

with Hilt

Arbaz Pirwani
@arbazpirwani
@arbazpirwani
What’s a dependency

● References to other classes to complete some work

● All apps have dependencies

Dependency

Engine

Car
Dependency Injection (DI)

● Dependencies are provided to a class instead of the class creating them itself

Engine

Engine

Car
Without DI
class Car {
private val engine: Engine = Engine()
}

Engine

Car
With DI
class Car(private val engine: Engine) {

Engine

Car
You should ALWAYS
apply DI principles
to your app!
Importance of DI

● Reusability of code
Reuse Car
fun main(args: Array<String>){

val electricCar = Car(ElectricEngine())


val combustionCar = Car(CombustionEngine())

...
}
Importance of DI

● Reusability of code

● Good balance of loosely-coupled dependencies


Importance of DI

● Reusability of code

● Good balance of loosely-coupled dependencies

● Ease of refactoring
class Car {

// Very, very long source code

}
class Car(
private val engine: Engine
) {

// Very long source code

}
class Car(
private val engine: Engine,
private val battery: Battery,
private val airFilter: AirFilter,
private val radiator: Radiator,
private val wipers: List<Wiper>,
...
) {
// Small source code
}
Engine Radiator

Car
Car

Battery Wiper
DI benefits

● Reusability of code

● Good balance of loosely-coupled dependencies

● Ease of refactoring
○ Smaller - focused classes

● Ease of testing
Ease of Testing
class CarTest {

@Test
fun `Car happy path`() {
val car = Car(FakeEngine())
...
}
}
Ease of Testing
class CarTest {

@Test
fun `Car happy path`() {
val car = Car(FakeEngine())
...
}

@Test
fun `Car with failing Engine`() {
val car = Car(FakeFailingEngine())
...
}
}
Choosing the right tool

Project Size Small Medium Large

Manual DI
Tool to Use Service Locator Hilt/Dagger Hilt/Dagger
Hilt/Dagger
Manual DI

● Boilerplate

● Error-prone
iosched’s FeedViewModel
class FeedViewModel (
private val loadCurrentMomentUseCase: LoadCurrentMomentUseCase,
loadAnnouncementsUseCase: LoadAnnouncementsUseCase,
private val loadStarredAndReservedSessionsUseCase:
LoadStarredAndReservedSessionsUseCase,
getTimeZoneUseCase: GetTimeZoneUseCase,
getConferenceStateUseCase: GetConferenceStateUseCase,
private val timeProvider: TimeProvider,
private val analyticsHelper: AnalyticsHelper,
private val signInViewModelDelegate: SignInViewModelDelegate,
themedActivityDelegate: ThemedActivityDelegate,
private val snackbarMessageManager: SnackbarMessageManager
): ViewModel(),
FeedEventListener,
ThemedActivityDelegate by themedActivityDelegate,
SignInViewModelDelegate by signInViewModelDelegate {

}
https://github.com/google/iosched
Manual DI
Service Locator

Cost

Dagger

Hilt

App Size
Use Hilt!
Hilt
● Google use it internally

● We use it internally

● Steep learning curve 😔


Guidance
… and a Codelab!
https://developer.android.com/codelabs/android-hilt
https://developer.android.com/codelabs/android-dagger-to-hilt
DP ALERT
Why is DI hard in Android?
Why is DI hard in Android?

● Fragment classes are instantiated by the SDK

○ Activity
○ Service
○ Broadcast Receiver
● OS will create those for you
● You don’t own those constructor
What about Dagger?

● Hard to configure

● Multiple path to do the same thing


49%
of developers asked
for DI solution
* Developer Benchmark survey 2020
DI solutions Goals

● Opinionated

● Easy to setup

● Lets you focus on what is important


Hilt to the rescue!!!
Hilt

● Jetpack’s recommended DI solution for Android

● Remove boilerplate via annotation

● Generates the code to manage dependencies

● Built on top of Dagger

● Tooling Support

● Jetpack Extension
Quick start guide
@HiltAndroidApp
class MyAndroidApp : Application()

@AndroidEntryPoint
class LoginActivity : AppCompatActivity() { /* ... */}
Quick start guide
@AndroidEntryPoint
class HomeActivity : AppCompatActivity() {

@Inject lateinit var appEvents: AppEvents

override fun onCreate(savedInstance: Bundle) {


super.onCreate(savedInstance)
appEvents.logBasicEvent(HOME_SCREEN_VISIT)
}
}
Quick start guide
class AppEvents @Inject constructor() {

fun logBasicEvent(eventName: String) { ... }

}
Annotations recap

● @Inject

● @AndroidEntryPoint

● @HiltAndroidApp
Bindings

● Unscoped bindings: available in all components if not installed in Modules

● Scoped bindings: scoped to one components and inherited by subcomponents


Jetpack Extensions

● ViewModel

● Navigation

● Compose

● WorkManager
iosched’s FeedViewModel
@HiltViewModel
class FeedViewModel @Inject constructor(
private val loadCurrentMomentUseCase: LoadCurrentMomentUseCase,
loadAnnouncementsUseCase: LoadAnnouncementsUseCase,
private val loadStarredAndReservedSessionsUseCase:
LoadStarredAndReservedSessionsUseCase,
getTimeZoneUseCase: GetTimeZoneUseCase,
getConferenceStateUseCase: GetConferenceStateUseCase,
private val timeProvider: TimeProvider,
private val analyticsHelper: AnalyticsHelper,
private val signInViewModelDelegate: SignInViewModelDelegate,
themedActivityDelegate: ThemedActivityDelegate,
private val snackbarMessageManager: SnackbarMessageManager
): ViewModel(),
FeedEventListener,
ThemedActivityDelegate by themedActivityDelegate,
SignInViewModelDelegate by signInViewModelDelegate {
}
https://github.com/google/iosched
iosched’s FeedFragment
@AndroidEntryPoint
class FeedFragment : MainNavigationFragment() {

private val model: FeedViewModel by viewmodels()


// ...
}
One more thing…

● Dagger and Hilt can work together

● Migration APIs available

● Migration guide:

○ dagger.dev/hilt/migration-guide
goo.gle/hilt-cheatsheet
Takeaways

● Always use Dependency Injection

● Use Hilt

● Check out the guidance!

You might also like