오늘도 더 나은 코드를 작성하였습니까?

Android Code Lab(Hilt) 정리3 본문

DI/Hilt

Android Code Lab(Hilt) 정리3

hik14 2021. 12. 23. 20:26

UserComponent 이전하기.

 

UserComponent에는 Scope @LoggedUserScope 주석이 추가됩니다.

즉, UserComponent @LoggedUserScope 주석이 있는 클래스에 동일한 UserManager 인스턴스를 삽입합니다.

 

UserComponent의 수명주기는 Android 클래스에 의해 관리되지 않으므로 사용 가능한 Hilt 구성요소에 매핑되지 않습니다.

생성된 Hilt 계층구조 중간에 맞춤 구성요소를 추가하는 작업은 지원되지 않는다.

 

1. hilt와 Dagger를 같이 사용한다.

2. Scope가 지정된 Component를 사용 가능한 가장 가까운 Hilt Component(이 경우 SingleTonComponent)로 이전하고

필요한 경우 null 허용 여부를 사용한다

 

두가지 어느 방법 가능하다. 

 

codeLab에서는

 

UserComponent는 Hilt의 SingleTonComponent 일부로 이전시킨다.

이전시킬 Component에 모듈이 있는 경우 SingleTonComponent에도 Installed해야 한다.

 

UserComponent에서 Scope가 정해진 type은 UserDataRepository뿐이며 @LoggedUserScope 주석이 붙혀졌다.

UserComponent가 Hilt의 SingleTonComponent와 만나게 되므로 UserDataRepository에는 @Singleton 주석이 추가되며,

개발자는 사용자가 로그아웃할 때 로직을 통해 UserDataRepository를 null로 변경한다.

 

UserManager에는 이미 @Singleton 주석이 추가되어 있습니다. 즉, 앱 전체에서 동일한 인스턴스를 제공하고, 조금만 변경하여 Hilt와 동일한 기능을 달성할 수 있습니다. 

 

 

1. UserManager  작동 방식을 변경

 

- UserComponent의 인스턴스를 만들 필요가 없으므로 생성자에서 UserComponent.Factory 매개변수를 UserDataRepository로 바꿉니다. 그럼 대신 UserDataRepository가 종속 항목으로 포함된다.

- isUserLoggedIn(), userJustLoggedIn(), registerUser(), loginUser() 적절하게 수정.

UserManager.kt

private const val REGISTERED_USER = "registered_user"
private const val PASSWORD_SUFFIX = "password"

@Singleton
class UserManager @Inject constructor(
    private val storage: Storage,
   private val userDataRepository: UserDataRepository
) {

    val username: String
        get() = storage.getString(REGISTERED_USER)

    fun isUserRegistered() = storage.getString(REGISTERED_USER).isNotEmpty()

    fun registerUser(username: String, password: String) {
        storage.setString(REGISTERED_USER, username)
        storage.setString("$username$PASSWORD_SUFFIX", password)
        userJustLoggedIn(username)
    }

    fun unregister() {
        val username = storage.getString(REGISTERED_USER)
        storage.setString(REGISTERED_USER, "")
        storage.setString("$username$PASSWORD_SUFFIX", "")
        logout()
    }

    fun loginUser(username: String, password: String): Boolean {
        val registeredUser = this.username
        if (registeredUser != username) return false

        val registeredPassword = storage.getString("$username$PASSWORD_SUFFIX")
        if (registeredPassword != password) return false

        userJustLoggedIn(username)
        return true
    }

    fun isUserLoggedIn() = userDataRepository.username != null

    fun logout() {      
        userDataRepository.cleanUp()
    }

    private fun userJustLoggedIn(username: String) {
        userDataRepository.initData(username)
    }
}

2. UserDataRepository 작동방식을 변경한다.

 

- hilt의 관리될 @Singleton lifeclycle을 가진 종속 항목으로 포함되었기에 기존에 @LoggedUserScope를 삭제한다.

- 종속항목의 순환을 방지하기 위해서 기존에 생성자에서 주입을 받던 UserManager를 삭제한다.

- unreadNotifications, username  null 허용하는 type으로 변경한고 setter를 private로 설정한다.

- username  unreadNotifications를 임의의 숫자로 설정하는 새로운 함수 initData()를 생성

- cleanUp()을 추가하여 username을 null로 unreadNotifications를 -1로 설정합니다.

- randomInt() 함수를 클래스 본문 내부로 이동

UserDataRepository.kt

@Singleton
class UserDataRepository @Inject constructor() {

    var username: String? = null
        private set

    var unreadNotifications: Int? = null
        private set

    init {
        unreadNotifications = randomInt()
    }

    fun refreshUnreadNotifications() {
        unreadNotifications = randomInt()
    }
    fun initData(username: String) {
        this.username = username
        unreadNotifications = randomInt()
    }

    fun cleanUp() {
        username = null
        unreadNotifications = -1
    }

    private fun randomInt(): Int {
        return Random.nextInt(until = 100)
    }
}

 

3. MainActivity 수정

 

기존에 UserComponent에서 객체를 주입받기 위해 접근하던 코드를 제거

및 userManager 주입받을 필드생성.

    @Inject
    lateinit var userManager: UserManager

4. SettingsActivity 수정

 

기존에 UserComponent에서 객체를 주입받기 위해 접근하던 코드를 제거

 

5. UserComponent 및 AppSubComponent 삭제

 

*LoggedUserScoped 도 삭제한다. 

 

'DI > Hilt' 카테고리의 다른 글

Android Code Lab(Hilt) 정리2  (0) 2021.12.23
Android Code Lab(Hilt) 정리1  (0) 2021.12.23
Hilt을 사용한 종속성 주입  (0) 2021.05.06