본문 바로가기

Android Library

[Android Library] Hilt (3) - hilt in MVVM

안녕하세요.

 

안드로이드에서 가장 많이 사용되는 디자인 패턴이 MVVM (Model - View - ViewModel) 입니다.

MVVM 디자인 패턴에서 Hilt가 어떻게 쓰이는지 알아보겠습니다.


Code

https://github.com/aregpetrosyan/Android-MVVM-Boilerplate-Hilt

 

GitHub - aregpetrosyan/Android-MVVM-Boilerplate-Hilt: A sample project in Kotlin to demonstrate AndroidX, MVVM, Coroutines, Hilt

A sample project in Kotlin to demonstrate AndroidX, MVVM, Coroutines, Hilt, Room, Data Binding, View Binding, Retrofit, Moshi, Leak Canary and Repository pattern. - GitHub - aregpetrosyan/Android-M...

github.com

위 코드가 MVVM 패턴과 hilt를 사용하는 프로젝트입니다.

 

해당 깃허브에서 코드를 가져왔습니다.

Hilt 실제 사용 사례를 같이 보도록 하겠습니다.


Application

@HiltAndroidApp 어노테이션이 쓰인 것을 볼 수 있습니다.

@HiltAndroidApp
class Application : Application() {

    override fun onCreate() {
        super.onCreate()
        if (BuildConfig.DEBUG) {
            Timber.plant(Timber.DebugTree())
        }
    }

}

Activity

@AndroidEntryPoint 어노테이션이 쓰였습니다.

@AndroidEntryPoint
class MainActivity : AppCompatActivity(R.layout.activity_main)

Fragment

@AndroidEntryPoint 어노테이션을 Activity 말고도 다른 안드로이드 컴포넌트에 쓸 수 있습니다.

Fragment에서도 쓰인 것을 확인할 수 있습니다.

 

@Inject 어노테이션을 통해 adapter 변수를 hilt를 통해 할당 받습니다.

@AndroidEntryPoint
class UserListFragment : Fragment() {
    @Inject
    lateinit var adapter: UsersListAdapter

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        ...

        adapter.submitList(it)
    }

    ...
}

ViewModel

@HiltViewModel 어노테이션이 쓰입니다.

 

UserListViewModel을 쓰는 Activity에서 hilt를 통해 의존성 주입을 받아야하기 때문에

constructor 앞에 @Inject 어노테이션이 붙습니다.

@HiltViewModel
class UserListViewModel @Inject constructor(
    private val userListRepository: UserListRepository
) : ViewModel() {

    ...
}

Adapter

해당 어댑터는 Fragment에서 사용합니다.

스코프 범위가 FragmentScoped인 것을 확인할 수 있습니다.

@FragmentScoped
class UsersListAdapter @Inject constructor(val clickListener: ClickListener) :
    ...
}

Repository

class UserListRepository @Inject constructor(
    private val userListService: UserListService,
    private val database: UsersDatabase
) {

    ...
}

Module

@InstallIn 어노테이션으로 범위를 지정할 수 있습니다.

Singleton으로 사용하는 것을 확인할 수 있습니다.

 

@Provides 어노테이션으로 구체적인 구현체를 만들 수 있습니다.

외부 라이브러리 (Room)의 구현체를 만들기 위해 사용됩니다.

@InstallIn(SingletonComponent::class)
@Module
object DatabaseModule {
    @Provides
    @Singleton
    fun provideAppDatabase(@ApplicationContext appContext: Context): UsersDatabase {
        return Room.databaseBuilder(
            appContext,
            UsersDatabase::class.java,
            "Users"
        ).fallbackToDestructiveMigration().build()
    }

    @Provides
    fun provideChannelDao(usersDatabase: UsersDatabase): UsersDao {
        return usersDatabase.usersDao
    }

}