안녕하세요, 오늘은 Hilt에 대해 알아보려 합니다.
우선 알아보기 전에 의존성 주입이라는 개념에 대해 이해해야 하는데요
저의 이전 글을 참고하거나 구글링을 통해 개념을 조금 파악하시기 바랍니다
2021.08.24 - [Android Studio/Dependency] - 의존성 주입이란?
우선 Dagger2라는 의존성 주입 라이브러리는 러닝 커브가 높고 어렵습니다. 하지만 이런 Dagger2를 쉽게 사용할 수 있게 나온 것이 바로 Dagger Hilt입니다
Hilt는 여러분이 생각하는 것 그 이상으로 더 간단하고 이 글 한 개로도 충분이 사용하실 수 있을 겁니다
이 글에서는 간단하게 GithubApi를 Retrofit을 이용하여 호출하는 예시를 보여드립니다
깃허브 코드는 아래 링크에 있습니다
https://github.com/ParkSangSun1/Github_RxKotlin
@HiltAndroidApp
App.kt
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class App : Application() {
private var instance: App? = null
override fun onCreate() {
super.onCreate()
instance = this
}
}
먼저 Hilt를 사용하기 위해선 @HiltAndroidApp 어노테이션을 앱 시작할 때 실행시켜줘야 합니다. 때문에 Application()을 상속받은 App이라는 클래스에 어노테이션을 선언해주고 이 클래스를 AndroidManifest.xml에서 name으로 설정해줍니다
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pss.github_rxkotlin">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:name="com.pss.github_rxkotlin.di.App"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Quick_Setup">
<activity
android:name="com.pss.github_rxkotlin.view.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
이렇게 하면 준비운동은 끝이 납니다! 참 쉽죠?
@Module, @InstallIn(SingletonComponent::class), @Provides
외부 라이브러리 (Retrofit, Okhttp 등)는 Hilt가 어떻게 객체를 생성해야 하는지 방법을 모르기 때문은 @Modules를 사용해 우리가 알려줘야 합니다
@InstallIn(SingletonComponent::class)는 해당 모듈을 싱글턴으로 사용하겠다는 의미입니다
그러고 나서 클래스 안의 함수 앞에 @Provides, @Singletion 어노테이션을 붙여줍니다
NetworkModule.kt
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideHttpClient(): OkHttpClient {
return OkHttpClient.Builder()
.readTimeout(10, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.addInterceptor(getLoggingInterceptor())
.build()
}
@Singleton
@Provides
fun provideRetrofitInstance(
okHttpClient: OkHttpClient,
gsonConverterFactory: GsonConverterFactory
): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.client(provideHttpClient())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(gsonConverterFactory)
.build()
}
@Provides
@Singleton
fun provideConverterFactory(): GsonConverterFactory {
return GsonConverterFactory.create()
}
private fun getLoggingInterceptor(): HttpLoggingInterceptor =
HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }
@Provides
@Singleton
fun provideGithubApiService(retrofit: Retrofit): GithubApi {
return retrofit.create(GithubApi::class.java)
}
}
Retrofit을 사용하기 위한 NetworkModule입니다
RepositoryModule.kt
@Module
@InstallIn(SingletonComponent::class)
class RepositoryModule {
@Provides
@Singleton
fun provideMainRepository(
githubApi: GithubApi
) = MainRepository(githubApi)
}
ViewModel에 Repository를 주입해서 사용하기 위한 Module
이곳에서 위에 선언한 NetworkModule의 provideGithubApiService함수를 이용해 GithubApi 의존성 주입을 받습니다
@HiltViewModel, @Inject
@Inject은 의존성 주입을 받겠다는 의미입니다. 사용할 때는 반드시 constructor()과 함께 사용해야 합니다.
위에서 RepositoryModule를 만들어주었고 반환형이 MainRepository인 provideMainRepository 함수를 선언했기 때문에 의존성 주입이 가능하게 됩니다
일반적인 클래스에서는 이렇게 @Inject를 사용해 의존성 주입을 받을 수 있지만 ViewModel에서는 @HiltViewModel이라는 어노테이션을 사용해야 합니다. 하지만 정말 이 한 줄만 추가로 사용하면 끝나기 때문에 그렇게 어렵지 않다는 점!
@HiltViewModel
class MainViewModel @Inject constructor(
private val mainRepository: MainRepository
) : ViewModel() {
fun getUserInfo(owner: String) = mainRepository.getUserInfo(owner)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe({ items ->
items.forEach { println(it) }
}, { e ->
println(e.toString())
})
}
@AndroidEntryPoint
ViewModel까지 만들었다면 이제 이것을 사용할 activity가 필요할 겁니다
이때 ViewModel을 사용하는 activity에 @AndroidEntryPoint를 이용해 사용할 수 있습니다
Fragment에서 사용한다면 Fragment가 붙어있는 activity에 @AndroidEntryPoint를 붙여 사용할 수 있습니다
@AndroidEntryPoint
class MainActivity : BaseActivity<ActivityMainBinding>(R.layout.activity_main) {
private val mainViewModel by viewModels<MainViewModel>()
override fun init() {
binding.activity = this
}
fun clickSearchBtn(view: View){
mainViewModel.getUserInfo(binding.name.text.toString())
}
}
이렇게만 해줘도 Hilt를 이용해 쉽게 GithubApi를 호출해볼 수 있습니다!!
추가로
안드로이드 개발에 대한 질문과 정보 등을 공유 및 소통하는 채팅방입니다
'Android' 카테고리의 다른 글
[Jetpack compose] Text를 사용해 보자! (0) | 2022.03.03 |
---|---|
[Android] Library를 만들고 JitPack으로 배포해보자! (0) | 2021.12.30 |
Clean Architecture + MVVM + Coroutine + Hilt + Retrofit을 이용하여 안전하게 Github API를 호출해 보자! (0) | 2021.12.27 |
Android Clean Architecture를 지향한 MVVM 패키지 구조 (0) | 2021.12.16 |
Android MVVM 패키지 구조 (0) | 2021.12.16 |