내일배움캠프 56일차

김재현·2024년 5월 21일

오늘은 inner class 수정하고 Hilt에 대해서 공부해보았다.

  • 원래는 MyViewHolder가 inner class로 작성되어 있었는데 최대한 지양하라고 튜터님께서 말씀하셔서 onclick 파라미터를 생성해 해결해주었다. 간단!

Hilt

  • Hilt는 안드로이드의 의존성 주입 라이브러리이다.

여기서 의존성 주입이란?? 생성자 또는 메서드 등을 통해 외부로부터 생성된 객체를 전달받는 행위를 의미한다. 의존성 주입을 통해 클래스간 결합도를 느슨하게 만들고 코드를 유연하게 변경 가능하도록 한다.

  • Hilt의 사용 이유
    DI, 즉 Dependency Injection은 객체 간의 의존성을 외부에서 주입하는 프로그래밍 기법입니다. 이 방법은 객체가 자신을 필요로 하는 의존성을 직접 생성하지 않고 외부로 부터 받아 사용하는데 이 방법을 사용하는 이유는 코드의 결합도를 낮추고 재사용성 및 테스트 용이성을 향상시키는 것 때문입니다.

Hilt를 사용하면 간단한 어노테이션을 통해 의존성을 쉽게 주입할 수 있습니다. 어노테이션을 액티비티나 프래그먼트에 추가함으로써 Hilt가 필요한 의존성을 해당 컴포넌트에 자동으로 주입하도록 할 수 있습니다. 또한 Hilt는 애플리케이션의 다양한 수명 주기를 고려하여 의존성을 관리하므로 메모리 누수와 같은 문제를 방지하는 데에도 도움이 됩니다.

1줄 요약 : Hilt는 안드로이드 개발에서 DI를 더 쉽고 효율적으로 사용할 수 있게 해주는 도구이며 코드의 유지 보수성과 확장성을 크게 향상시킬 수 있다.

class Engine{}
class Car {
	val engine = Engine()
}

다음과 같은 클래스 두개가 있다면 Car 클래스 내에서 직접 Engine을 생성하는 책임을 가지고 있다.

  • 제어의 역전(IoC)
class Car (val engine: Engine){}

Car 클래스가 Engine 생성의 책임을 제거! -> Engine을 외부에서 전달 받을 수 있게 되면 Car는 Engine 생성에 대한 책임이 없다 -> 제어의 역전

  • Injector

의존성을 클라이언트에게 제공하는 역할을 한다.

class Injector {
	fun getEngine() {
    	return Engine()
    }
}

fun main(args: Array<String>) {
	val engine = Injector().getEngine()
    val car = Car(engine)
}

-> Injector는 Engine 클래스에 의존하고 있다.
Injector는 Car 클래스에게 의존성을 주입해주고 있다.
Car 클래스는 Engine 클래스를 참조하고 있다.

  • 위 코드를 Hilt 적용해보면 다음과 같다.
class Car {
	private val engine : Engine
	private val wheels : Wheels 
	
	fun Car() {
		engine = Engine() 
		wheels = Wheels() 
		}
		
	fun Drive() {
		}

@Inject lateinit var car : Car
onCreate() {
	car.drive()
}

Hilt Annotation

  • Provides

클래스가 외부 라이브러리에서 제공되어 생성자 삽입이 불가능한 경우 (ex. Retrofit, Room)

@Module
@InstallIn(SingletonComponent::class)
internal object RetrofitClient {
    @Provides
    fun provideOkHttpClient(): OkHttpClient {
        val loggingInterceptor = HttpLoggingInterceptor()
        loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY

        return OkHttpClient
            .Builder()
            .addInterceptor(HttpRequestInterceptor())
            .addNetworkInterceptor(loggingInterceptor)
            .build()
    }
  • Binds

Interface는 생성자 삽입이 불가능한데 Interface의 인스턴스를 제공해야 할 때 사용한다.

@Module
@InstallIn(SingletonComponent::class)
internal interface SearchModule {
    @Binds
    fun bindsSearchRepository(searchRepositoryImpl: SearchRepositoryImpl) : SearchRepository
}
  • HiltAndroidApp

HiltAndroidApp은 Hilt 컴포넌트의 코드 생성과 컴포넌트를 사용하는 Application의 기본클래스를 생성하여 onCreate() 호출 후 Application 필드에 의존성 주입이 이루어짐

@HiltAndroidApp
class StandardApp: Application()
  • AndroidEntryPoint

Application에서 멤버 주입이 가능하게 설정하면, 안드로이드 클래스에 AndroidEntryPoint 어노테이션을 사용하여 멤버주입을 해줘야 한다.

  • AndroidEntryPoint 사용할 수 있는 타입
    • Activity
    • Fragment
    • View
    • Service
    • BroadcastReceiver
@AndroidEntryPoint
class GitHubUserFragment : Fragment() { ... }
  • InstallIn

    • Hilt 표준 컴포넌트들 중 어떤 컴포넌트에 모듈을 설치할 지 결정
    • Hilt 컴포넌트가 생성될 때 모듈들은 추가된 InstallIn과 함께 알맞은 컴포넌트, 서브 컴포넌트에 설치
    • 컴포넌트 내 다른 바인딩 또른 하위 컴포넌트에 바인딩이 접근하는 것을 허용

.
.
.
.
.

강의 들으면서 한번 실행해봤는데...

실행하자마자 멸망했다 흐규ㅠㅠㅠㅠㅠㅠㅠㅠㅠ

하루의 마무리

  • 어렵다 어려워...

0개의 댓글