Grusie 안드로이드 개발 기술 블로그

[Android] 뷰모델에 런타임 오브젝트 의존성 주입하기(@AssistedInject) 본문

안드로이드 개발

[Android] 뷰모델에 런타임 오브젝트 의존성 주입하기(@AssistedInject)

grusie 2024. 6. 26. 16:25
728x90
반응형
SMALL

기존 HiltViewModel을 사용했을 때에는 생성자에 의존성이 선언 되어있는 useCase들을 넘겨주는 형태로 사용하였으나, 생성자를 넣어주고 싶어 찾아보다 Assisted Inject에 대해 발견하게 되어 기록해보려고 한다.

 

사용법

1. @HiltViewModel을 사용하지 않는다.

2. 뷰모델의 constructor 앞에 @Inject를 @AssistedInject로 대체한다.

3. 생성자에 들어갈 파라미터 중 런타임 오브젝트를 주입받는 파라미터에는 @Assisted 애너테이션을 넣는다.

4. 생성자를 주입한 뷰모델을 리턴하는 뷰모델 팩토리를 선언한다.

5. 뷰에서 뷰모델 팩토리를 사용하여, 뷰모델을 생성한다.

 

직접 구현해보자

class SlowMailBoxViewModel @AssistedInject constructor(
    private val getLocalUserInfoUseCase: GetLocalUserInfoUseCase,
    private val setLocalUserInfoUseCase: SetLocalUserInfoUseCase,
    private val slowMailBoxUseCases: SlowBoxUseCases,
    @Assisted private val spaceId: Long,
    @Assisted private val slowMailType: Int?
) : ViewModel() {
	...
}

 

해당 뷰모델에 @AssistedInject constructor로 필요한 파라미터를 입력해주고, 동적으로 런타임에 주입받을 파라미터에@Assisted를 입력해준다.

Hilt ViewModel을 사용하는 것이 아니라, @HiltViewModel을 사용하지 않는다. 

 

참고)

HiltViewModel을 사용하면서, 동적으로 런타임에 주입받을 파라미터가 존재한다면, SavedStateHandle을 사용하여 뷰모델 팩토리에서 생성해주면 될 것 같다.

 

뷰모델 팩토리 선언

@AssistedFactory
interface SlowMailBoxViewModelFactory {
    fun create(spaceId: Long, slowMailType: Int?): SlowMailBoxViewModel
}

뷰모델 팩토리를 인터페이스로 선언을 해준 뒤, create를 통해 뷰모델을 생성할 예정이다.

런타임에 주입받을 파라미터는 spaceId, slowMailType 이렇게 두 개이다.

spaceIdslowMailType은, SlowMailBoxViewModel을 사용하기 위해 꼭 필요한 파라미터로서, 다음 페이지로 이동할 때에도 사용될 것이며 한 번 지정되면 변경이 되지 않고, 이 값들에 따라서 서버통신을 진행하기에 생성자 파라미터로 넘겨주는 것을 택했다.

 

create()함수 구현

companion object {
    fun provideFactory(
        slowMailBoxViewModelFactory: SlowMailBoxViewModelFactory,
        spaceId: Long,
        slowMailType: Int?
    ): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return slowMailBoxViewModelFactory.create(spaceId, slowMailType) as T
        }
    }
}

뷰모델 팩토리에서, viewModel을 생성해주는 create함수를 오버라이딩 해, 우리가 구현했던, SlowMailBoxViewModelFactory를 통해서 뷰모델을 생성하도록 구현하였다.

 

뷰모델을 사용할 액티비티

private var spaceId: Long = 0
private var slowMailType: Int = 0

@Inject
lateinit var slowMailBoxViewModelFactory: SlowMailBoxViewModel.SlowMailBoxViewModelFactory

private val viewModel by viewModels<SlowMailBoxViewModel> {
    SlowMailBoxViewModel.provideFactory(slowMailBoxViewModelFactory, spaceId, slowMailType)
}

 

뷰모델 팩토리를 @Inject 애너테이션을 추가하여, lateinit으로 생성 후, 각 파라미터들을 사용해서  ViewModel을 생성하도록 구현

 

spaceId = intent.getLongExtra(SlowMailBoxActivity.EXTRA_SPACE_ID, 0)
slowMailType = intent.getIntExtra(EXTRA_TYPE, TYPE_RECEIVED)

이전 화면에서 뷰모델에 들어갈 파라미터들을 Intent로 받아와 넣어주며, 추 후 뷰모델이 사용될 어딘가에서, 뷰모델이 생성될 것이다.

 

런타임에서 생성자에 파라미터를 넣었을 때의 장점

 

1. 뷰모델에서 초기 데이터를 init 함수에서 가져올 수 있다.

init {
    if(slowMailType == null) fetchData() else fetchDataWithType()
}

 

2. 생성자를 setter로 지정했을 경우, 코드 실수를 했을 때 컴파일 에러로 판단할 수 없다.

3. 테스트 코드 작성 시 필요한 데이터 주입을 간단히 할 수 있다.

 

참고

https://velog.io/@victorywoo/Android-Dagger-Hilt-Assisted-Inject-%EB%9F%B0%ED%83%80%EC%9E%84-%EC%A3%BC%EC%9E%85

 

[Android] Dagger Hilt Assisted Inject - 런타임 주입

AssistedInject에 대해서 알아보려고 한다. AssistedInject 기존 Hilt를 사용했을 때는 미리 명시된 의존 Graph에서 명시적으로 정의된 Module만을 주입받을 수 있었다. 하지만, AssistedInject를 통해서 런타임에

velog.io

https://medium.com/@saqwzx88/dagger-hilt-assistedinject-%EB%9F%B0%ED%83%80%EC%9E%84-%EC%A3%BC%EC%9E%85%ED%95%98%EA%B8%B0-871c15d952bf

 

Dagger Hilt Assisted Inject— 런타임 주입하기

Hilt 2.31 버전 이후로, AssistedInject란 기능이 새로 생겼습니다.

medium.com

 

후기

생성자에 필요한 정보들을 setter를 사용해서 넣었었는데, 그랬기에 init함수에서 데이터를 가져오지 못하고, setter 호출 후, fetchData()를 직접 호출해주었어야 했다.

이렇게 변경하고 나니, 뷰에서 신경쓸 코드가 더 줄어들어서 유지보수성을 증가시킬 수 있었던 것 같다.

 

반응형
LIST