일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- designPattern
- Observer Pattern
- ㅋㅁ
- factory method
- 빌터패턴
- Singleton
- F
- PrototypePattern
- 옵저버 패턴
- ㅓ
- 디자인패턴 #
- 추상 팩토리
- builderPattern
- 코틀린
- 싱글톤
- El
- 팩토리 메소드
- Design Pattern
- Functional Programming
- a
- r
- Kotlin
- 함수형프로그래밍
- Abstract Factory
- 추상팩토리패턴
- 디자인패턴
- 프로토타입 패턴
- Today
- Total
오늘도 더 나은 코드를 작성하였습니까?
Android Code Lab(Hilt) 정리1 본문
기존 Dagger를 통한 의존성 주입을 적용한 프로젝트를 Hilt로 이전한다.
이전 하는 작업을 단계별로 정리하고자, @Singletone Component를 이전을 시작하여
나중에 Activity 및 Fragment를 이전시킨다.
@Component 및 @Subcomponent 인터페이스를 제거하고, @InstallIn으로 모든 모듈에 주석을 추가한다!
hilt로 모든 이전이 완료되면,
Application/Activity/Fragment/View/Service/BroadcastReceiver 클래스에는
@AndroidEntryPoint 주석이 있어야 하고 Component 인스턴스화하거나 전달하는 모든 코드는 존재해서는 안된다.
1. AppComponent.kt 계층 구조를 이해하기.
@Singleton
// Definition of a Dagger component that adds info from the different modules to the graph
@Component(modules = [StorageModule::class, AppSubcomponents::class])
interface AppComponent {
// Factory to create instances of the AppComponent
@Component.Factory
interface Factory {
// With @BindsInstance, the Context passed in will be available in the graph
fun create(@BindsInstance context: Context): AppComponent
}
// Types that can be retrieved from the graph
fun registrationComponent(): RegistrationComponent.Factory
fun loginComponent(): LoginComponent.Factory
fun userManager(): UserManager
}
AppComponent
AppComponent - StorageModule
|
- AppSubcomponents - LoginComponent -> LoginActivity
- UserComponent -> MainActivity / SettingsActivity
- RegistrationComponent -> RegistraionActivity, EnterDetails, TAC,
SingletonComponent에 대한 참조는 앱에서 이전하는 구성요소에 매핑되는
Hilt 생성 구성요소(생성된 모든 구성요소로 연결되는 링크)로 대체된다.
2. AppComponent 이전.
@HiltAndroidApp
- Application class에 추가하여 SingletonComponent(ApplicationComponent)를 자동 생성한다
- Hilt를 초기화하고 코드 생성을 시작
- Dagger가 annotation processor 픽업하여 사용할 코드 생성을 트리거하도록 Hilt에 알립니다.
MyApplication.kt
package com.example.android.dagger
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
open class MyApplication : Application() {
// Instance of the AppComponent that will be used by all the Activities in the project
val appComponent: AppComponent by lazy {
initializeComponent()
}
open fun initializeComponent(): AppComponent {
// Creates an instance of AppComponent using its Factory constructor
// We pass the applicationContext that will be used as Context in the graph
return DaggerAppComponent.factory().create(applicationContext)
}
}
기존 2개의 StorageModule, AppSubcomponents을 Hilt가 자동생성한, SingletonComponent추가한다.
@InstallIn은 매개변수를 사용하여 적절한 Component에 Module을 추가해준다.
@InstallIn(SingletonComponent::class) 주석을 통해 2개의 모듈을 SingletonComponent 에 추가한다.
StorageModule.kt
@InstallIn(SingletonComponent::class) // Hilt가 생성한 SingletonComponent 추가한다.
@Module // Dagger의 모듈임을 알린다.
abstract class StorageModule {
// Storage type 요청될 때 Dagger가 SharedPreferencesStorage를 주입/
@Binds
abstract fun provideStorage(storage: SharedPreferencesStorage): Storage
}
AppSubComponent.kt
@InstallIn(SingletonComponent::class)
@Module(
subcomponents = [
RegistrationComponent::class,
LoginComponent::class,
UserComponent::class
]
)
@DisableInstallInCheck
class AppSubcomponents
3. Exposed Type 이전.
Hilt @EntryPoint 을 사용하여 Dagger의 종속 항목을 직접 요청할 수 있습니다.
@EntryPoint을 사용하면 모든 Dagger Component를 이전하는 동안 앱이 계속 작동하도록 할 수 있습니다.
이 단계에서는 각 Dagger Component를 Hilt가 생성한 SingletonComponent의 수동 종속 항목 조회로 교체합니다.
Hilt에서 생성된 SingletonComponent에서 RegistrationActivity.kt를 위한 RegistrationComponent.Factory주입하기 위해 @InstallIn 주석이 추가된 새로운 EntryPoint Interface를 생성한다.
@InstallIn은 결합을 가져올 위치를 Hilt에 알려준다.
EntryPoint에 액세스하려면 EntryPointAccessors의 적절한 정적 메서드를 사용한다.
매개변수는 Component 인스턴스이거나 Component 소유자 역할을 하는 @AndroidEntryPoint 객체이다.
RegistrationActivity.kt
class RegistrationActivity : AppCompatActivity() {
@InstallIn(SingletonComponent::class)
@EntryPoint
interface RegistrationEntryPoint {
fun registrationComponent(): RegistrationComponent.Factory
}
...
}
Dagger 관련 코드를 RegistrationEntryPoint로 교체해야 한다.
RegistrationEntryPoint를 사용하도록 registrationComponent의 초기화를 변경합니다.
이 변경으로 RegistrationActivity가 Hilt를 사용하도록 이전될 때까지 Hilt에서 생성된 코드를 통해 종속 항목에 액세스할 수 있습니다.
남은 Component 대해 동일한 기본 작업을 해야 합니다.
LoginActivity.kt
class LoginActivity : AppCompatActivity() {
@Inject
lateinit var loginViewModel: LoginViewModel
@InstallIn(SingletonComponent::class)
@EntryPoint
interface LoginEntryPoint {
fun loginComponent(): LoginComponent.Factory
}
override fun onCreate(savedInstanceState: Bundle?) {
val entryPoint = EntryPointAccessors.fromApplication(applicationContext, LoginEntryPoint::class.java)
entryPoint.loginComponent().create().inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
.
.
.
}
AppComponent의 노출된 세 가지 유형 중 두 가지가 Hilt EntryPoint와 호환되도록 변경되었습니다.
UserManager를 비슷하게 변경해야 합니다.
RegistrationComponent, LoginComponent와 달리 UserManager는 MainActivity 및 SettingsActivity 모두에서 사용됩니다.
EntryPoint 인터페이스는 한 번만 선언하면 된다.
주석이 추가된 EntryPoint 인터페이스는 MainActivity 및 SettingsActivity 모두에서 사용될 수 있습니다.
간단히 하려면 MainActivity에서 인터페이스를 선언합니다.
MainActivity.kt
class MainActivity : AppCompatActivity() {
@InstallIn(SingletonComponent::class)
@EntryPoint
interface UserManagerEntryPoint {
fun userManager(): UserManager
}
val entryPoint = EntryPointAccessors.fromApplication(applicationContext, UserManagerEntryPoint::class.java)
val userManager = entryPoint.userManager()
.
.
.
}
SettingsActivity.kt
val entryPoint = EntryPointAccessors.fromApplication(applicationContext, MainActivity.UserManagerEntryPoint::class.java)
val userManager = entryPoint.userManager()
4. Component Factory 제거
@BindsInstance를 사용하여 Dagger 구성요소에 Context를 전달하는 것이 일반적인 패턴입니다.
Context가 사전 정의된 결합으로 이미 사용 가능한 상태이므로 이는 Hilt에서 필요하지 않습니다.
리소스, 데이터베이스, 공유 환경설정 등에 액세스하려면 Context가 필요합니다.
Hilt는 한정자 @ApplicationContext 및 @ActivityContext를 사용하여 Context에 삽입하는 작업을 단순화합니다.
앱을 이전하는 동안 Context를 종속 항목으로 요구하는 유형을 확인하고 Hilt에서 제공하는 유형으로 교체합니다.
SharedPreferencesStorage의 종속 항목으로 Context가 포함됩니다. 컨텍스트를 삽입하도록 Hilt에 알리려면 애플리케이션의 Context를 요구하는 SharedPreferences에 Context 매개변수에 @ApplicationContext 주석을 추가합니다.
SharePreferencesStorage.kt
class SharedPreferencesStorage @Inject constructor(
@ApplicationContext context: Context
) : Storage {...}
5. inject method
inject() 메서드의 Component 코드를 확인하고 해당 클래스에 @AndroidEntryPoint 주석을 추가해야 합니다.
지금은 AppComponent에 inject() 메서드가 없으므로 별도의 조치가 필요하지 않습니다.
6. AppComponent 삭제.
AppComponent.kt에 나열된 모든 구성요소에 EntryPoint를 이미 추가했으므로 AppComponent.kt를 삭제한다.
7. MyApplication.kt 수정
MyApplication에서 맞춤 AppComponent를 초기화하는 데 코드가 필요하지 않습니다.
Application 클래스가 Hilt에서 생성된 SingtonComponent를 사용합니다.
package com.example.android.dagger
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
open class MyApplication : Application()
'DI > Hilt' 카테고리의 다른 글
Android Code Lab(Hilt) 정리3 (0) | 2021.12.23 |
---|---|
Android Code Lab(Hilt) 정리2 (0) | 2021.12.23 |
Hilt을 사용한 종속성 주입 (0) | 2021.05.06 |