안드로이드에서 DI 라이브러리(Hilt) 도움 없이 수동으로 Container를 생성해 수동 의존성 주입을 공부해보자.
isLogin
Boolean 값은 true로 DataStore
에 저장된다.DataStore
에 저장된 isLogin
은 false가 된다.class LoginActivity : AppCompatActivity() {
private val viewModel: LoginViewModel by viewModels { ... }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
initView()
handleLoginUiState()
}
private fun handleLoginUiState() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect {
when (it.userState) {
UserState.NONE -> Unit
UserState.LOGGED_IN -> showToast("로그인 성공")
UserState.FAILED -> showToast("로그인 실패")
}
}
}
}
}
private fun initView() {
findViewById<Button>(R.id.btn_login).setOnClickListener {
viewModel.login()
}
findViewById<Button>(R.id.btn_logout).setOnClickListener {
viewModel.logout()
}
}
}
class AppContainer(private val context: Context) {
fun createLocalDataSource(): UserLocalDataSource = UserLocalDataSource(context)
fun createLocalDataRepository(): UserDataRepository = UserDataRepository(createLocalDataSource())
fun createLoginViewModelFactory(): AbstractSavedStateViewModelFactory {
return object : AbstractSavedStateViewModelFactory() {
override fun <T : ViewModel> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
): T {
return LoginViewModel(createLocalDataRepository()) as T
}
}
}
}
createLocalDataSource
, createLocalDataRepository
class AppContainer(private val context: Context) {
fun createLocalDataSource(): UserLocalDataSource = UserLocalDataSource(context)
var loginContainer: LoginContainer? = null
}
class LoginContainer(private val appContainer: AppContainer) {
fun createLocalDataRepository(): UserDataRepository = UserDataRepository(appContainer.createLocalDataSource())
fun createLoginViewModelFactory(): AbstractSavedStateViewModelFactory {
return object : AbstractSavedStateViewModelFactory() {
val localDataRepository = createLocalDataRepository()
override fun <T : ViewModel> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
): T {
return LoginViewModel(localDataRepository) as T
}
}
}
}
fun createLoginViewModelFactory(): AbstractSavedStateViewModelFactory {
return object : AbstractSavedStateViewModelFactory() {
override fun <T : ViewModel> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
): T {
return LoginViewModel(createLocalDataRepository()) as T
}
}
}
class App : Application() {
val appContainer: AppContainer = AppContainer(this)
}
class LoginActivity : AppCompatActivity() {
private val appContainer: AppContainer by lazy { (this.application as App).appContainer }
private val viewModel: LoginViewModel by viewModels { appContainer.loginContainer?.createLoginViewModelFactory() ?: error("not initialize") }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
appContainer.loginContainer = LoginContainer(appContainer)
setContentView(R.layout.activity_login)
initView()
handleLoginUiState()
...
...
override fun onDestroy() {
super.onDestroy()
// 생명주기에 따라 의존성 관리
appContainer.loginContainer = null
}
}
https://github.com/jiwon2724/DI-Container