Hilt를 사용하여 간단한 예제를 만들어볼게요. 이 예제에서는 Hilt를 사용해 자동차(Car)와 엔진(Engine) 객체를 생성하고, 의존성 주입을 통해 Car 객체가 Engine 객체를 사용할 수 있도록 하겠습니다.
이제 Engine과 Car 클래스를 정의합니다. Car 클래스는 Engine 객체에 의존합니다.
// Engine.kt
class Engine @Inject constructor() {
fun start() = "Engine is running"
}
// Car.kt
class Car @Inject constructor(private val engine: Engine) {
fun drive(): String {
return engine.start() + " and car is moving!"
}
}
Activity에서 Hilt 사용
이제 MainActivity에서 Hilt를 사용하여 Car 객체를 주입받아 사용해 보겠습니다.
// MainActivity.kt
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var car: Car // Car 객체를 Hilt가 주입해줍니다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Car 객체를 사용하여 drive() 메소드를 호출해 봅니다.
println(car.drive()) // "Engine is running and car is moving!" 출력
}
}
마지막으로, MainActivity에 @AndroidEntryPoint 애노테이션을 추가하여 Hilt가 이 액티비티에 의존성을 주입할 수 있도록 합니다.
// MainActivity.kt
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
// Hilt가 주입한 Car 인스턴스 사용
@Inject lateinit var car: Car
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
println(car.drive())
}
}
결과
앱을 실행하면, MainActivity에서 car.drive()를 호출했을 때, Engine 객체가 생성되어 Car 객체에 주입되고, Car는 이 Engine을 사용하여 "Engine is running and car is moving!"라는 메시지를 출력하게 됩니다.
요약
Engine: 자동차의 엔진 역할을 하는 클래스.
Car: 엔진을 주입받아 사용하는 자동차 클래스.
@Inject: Hilt가 의존성을 주입할 수 있도록 클래스나 변수에 표시.
@AndroidEntryPoint: Hilt가 Activity, Fragment 등에 의존성을 주입할 수 있도록 설정.
하지만 아직 모르겠다. 의존성을 직접 주입할 때와, hilt 를 사용했을 때와의 장점을..
만약 Engine 이 더 많은 의존성을 요구하게 된다면 어떻게 될까?
의존성이 복잡해진다는 것은 클래스들이 서로 얽혀서 의존성을 가지게 되거나, 여러 계층에 걸쳐 의존성이 주입되어야 하는 상황을 말합니다. 이런 상황에서 Hilt의 장점이 더 두드러지게 됩니다.
지금의 예제를 확장하여 더 복잡한 의존성을 가진 예시를 보여드리겠습니다.
시나리오 확장
Engine: 기존과 같이 horsepower와 engineType을 가지고 있습니다.
Transmission: 새롭게 추가된 Transmission 클래스는 변속기 유형을 나타내며, Car 클래스에서 필요로 합니다.
Driver: Car는 이제 운전자인 Driver를 필요로 합니다.
Car: Car 클래스는 이제 Engine, Transmission, Driver 세 가지 의존성을 가집니다.
class Engine @Inject constructor(
private val horsepower: Int,
private val engineType: String
) {
fun start(): String {
return "$engineType engine with $horsepower HP is running"
}
}
Transmission 클래스
class Transmission @Inject constructor(
private val type: String
) {
fun shift(): String {
return "Transmission type is $type"
}
}
Driver 클래스
class Driver @Inject constructor(
private val name: String
) {
fun drive(): String {
return "$name is driving"
}
}
Car 클래스
class Car @Inject constructor(
private val engine: Engine,
private val transmission: Transmission,
private val driver: Driver
) {
fun drive(): String {
return "${driver.drive()}, ${engine.start()}, and ${transmission.shift()}"
}
}
각 의존성에 필요한 값을 제공하는 Hilt 모듈을 설정합니다
@Module
@InstallIn(SingletonComponent::class)
object CarModule {
@Provides
fun provideHorsepower(): Int {
return 300
}
@Provides
fun provideEngineType(): String {
return "V12"
}
@Provides
fun provideTransmissionType(): String {
return "Automatic"
}
@Provides
fun provideDriverName(): String {
return "John Doe"
}
}
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var car: Car
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
println(car.drive())
// "John Doe is driving, V12 engine with 300 HP is running, and Transmission type is Automatic" 출력
}
}
Hilt 없이 복잡한 의존성 관리
만약 Hilt를 사용하지 않고 동일한 의존성을 관리하려면, MainActivity에서 모든 의존성을 직접 생성하고 Car 객체에 전달해야 합니다.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 의존성을 직접 생성
val engine = Engine(300, "V12")
val transmission = Transmission("Automatic")
val driver = Driver("John Doe")
// Car 객체 생성
val car = Car(engine, transmission, driver)
println(car.drive())
// "John Doe is driving, V12 engine with 300 HP is running, and Transmission type is Automatic" 출력
}
}