'WEB2.0/프로그래밍'에 해당되는 글 190건

dagger2 android viewmodel 과 사용하기

안드로이드 공식 문서에 있는 ViewModel의 간단한 예제이다

 

그도그럴것이 MyViewModel의 생성자에 아무런 인자가 없다

 

그러니깐 별도의 의존성을 고민할 필요 없이

 

ViewModelPrivoder를 통해 ViewModel을 생성해서 쓰면 된다

 

 

 

하지만 실제로는 생성자에 아무런 파라메터도 던져지지 않는 형태의 viewmodel을 쓰는 경우가 거의 없다

 

viewmodel이 UI에 표시할 데이터를 보여주기 위해 필요로 하는

 

여러 인스턴스들을 넘겨줘야한다(repository나 usecase 같은 것들)

 

 

 

그래서 안드로이드는 Factory라는 클래스를 통해서

 

viewmodel에 원하는 인자를 넣어 생성할수 있도록 하는 방법을 제공해준다

 

 

 

 

 

ViewModelProvider.Factory 를 구현 했다

 

위의 예제에서는 간단하게 string을 인자로 받는 MainViewModel을 생성했다

 

이 예제 처럼 create 메소드가 새 인스턴스를 리턴할때

 

무언가를 넣어서 인스턴스를 초기화할수 있다

 

즉 우리가 android viewmodel을 사용할때 가장 중요한것은

 

ViewModelFactory 클래스를 만들어서 해당 팩토리클래스가 적절한 viewmodel 클래스를 반환하도록 하는것에 있다

 

 

 

위의 예제처럼 ViewModelFactory를 구현해서 ViewModel을 생성할때 파라메터들을 직접 주입할수 있게 되었지만

 

아직 비효율적인 부분들이 남아있다

 

작은 앱에서는 이런 식의 구현이 나쁘지 않지만

 

우리가 만약 50개가 넘는, 100개가 넘는 viewmodel을 갖게 된다면

 

ViewModelFactory가 100개가 넘는 viewmodel의 생성자에 전달해줄 파라메터들까지 잔뜩 안고 있는

 

거대한 클래스가 되어버린다

 

 

바로 이때도 dagger가 이러한 의존성을 주입하는 역할을 할수있다

 

ViewModelFactory를 dagger를 이용해서 주입하는 방법을 사용해보자

 

먼저 ViewModelFactory를 만들어보자

 

ViewModelFactory 클래스의 생성자 파라메터인

 

Map 객체가 있는데 이게 뜬금없이 어디서 나온거지 당황스러울것이다

 

바로 이 Map 객체를 이후에 나올 코드의 @IntoMap 어노테이션이 자동으로 생성하게 된다

 

그러니깐 우리는 그냥 이 factory를 보고 간단히 factory 생성시에 전달될 map 객체는 

 

dagger가 알아서 주입하는구나라고만 생각하면된다

 

 

ViewModelFactoryModule은 @Binds를 사용했다

 

우리가 만든 클래스는 ViewModelFactory인데 필요한 타입은 추상화 되어있는 ViewModelProvider.Factory 클래스이라서

 

@Provides로 구현해도 되지만 @Binds 를 이용해서 간단하게 구현했다

 

 

여기서 중요한 포인트는

 

@JvmSuppressWildcards 어노테이션의 사용인데 나도 이걸 왜 필요로 하는건지 제대로 이해하지 못했다

 

다만 이 어노테이션이 없으면 빌드시에 에러가 나니깐 꼭 넣어야한다

 

 

 

 

자 이제 나머지 클래스의 구현을 살펴보자

 

 

 

MainViewModel과 SplashViewModel이라는 ViewModel을 예제를 위해 만들었다

 

예제에서는 아무런 생성자 파라메터가 없지만

 

생성자에서 필요한 repository라던지 usecase를 의존성 주입을 통해 넣으면 된다

 

 

ViewModelModule의

 

@IntoMap 어노테이션은 dagger로 하여금 이 리턴 타입을 map의 value에 넣으라고 알려준다

 

그럼 이제 map에 value는 들어갔으니 키로 사용될값이 필요한데

 

바로 @MapKey라는 어노테이션이 그 역할을 한다

 

ViewModelKey라는 어노테이션을 만들었다 그리고 여기에 @MapKey 어노테이션을 붙였다

우리 생성한 ViewModelKey 라는 어노테이션이 이후에 Key 로 사용할 값을 알려주는 역할을 한다

 

이후에 사용은 

 

@ViewModelKey(MainViewModel::class)


 

이런식으로 사용하게 되는데 괄호안에있는 값이 map의 key로 사용되어진다

 

 

 

이렇게 구현함으로서 dagger가 코드를 자동생성해내고

 

Map객체를 만들어주는데 key로는 Class 타입을, Value로는 ViewModel을 갖게된다

 

그렇기에 우리는 ViewModelFactory에서 map[modelClass]?.get()  이런식으로 원하는 ViewModel을 가져올수 있는것이다

 

ViewModelModule에서 공급하는 ViewModel은 추상화된 ViewModel 타입이 필요하므로

 

물론 @Binds 어노테이션을 사용해서 이렇게 구현해도 된다

 

 

자 이제 컴포넌트에서 ViewModelModule과 ViewModelFactoryModule을 연결하면 끝

 

이렇게 액티비티까지 완성하여 우리가 원하는 dagger + android view model의 조합을 완성했다

 

 

 

코드스니펫만으로는 설명에 한계가 있어서

 

보다 실무에 가까운 샘플코드를 만들었다

 

android viewmodel과 dagger를 조합한 완전한 예제를 github에 올려두었다

 

 

https://github.com/spotlight21c/DaggerViewModel

 

조금이나마 도움이 되길

| 1 | 2 | 3 | 4 | ··· | 190 |