본문 바로가기
📱 Android

[Android] MVVM 구현하기

by 콩드로이드 2022. 6. 27.

안녕하세요  :)  

이전 포스팅에서 MVVM에 대해 알아봤습니다만,

2022.05.30 - [Android] - [Android] Pattern (MVC, MVP, MVVM)

막상 MVVM으로 구현하려니,  적용이 꽤나.. 어려웠습니다 🥶

그래서 MVVM을 구현 시 알아둬야할 부분에 대해 자세한 개념보다는 어떻게 써야하는지를 정리하려고 합니다 

.. 멀고도 험한 MVVM의 길 😮‍💨

 

 

⚒ Skill ⚒

- ViewModel

- LiveData

- DataBinding

- Repository

- Dagger


ViewModel

- AAC (Clean Architecture을 쉽게 구현하도록 제공되는 library) 중 하나

- LifeCycle을 고려해 UI 관련 데이터를 저장하고 관리

 

👀 ViewModle을 사용하는 이유

화면 회전, 시스템 폰트 크기 변경 등 구성이 변경 시 액티비티가 재시작되며 데이터가 날아가기 때문에, 데이터 저장 및 복원 작업이 필요합니다.

물론 기존에 방법이 없었던 것은 아니에요. onSaveInstanceState()를 사용할 수도 있습니다

 

하지만, 기존 방법엔 문제점이 있어요 

   1) 저장할 수 있는 데이터의 양이 적다

   2) fun onCreate(savedInstanceState: Bundle?)에서 데이터를 저장 및 복원하는 처리가 필요합니다

       UI Controller는 최소한의 로직을 가져야 하는데, 이 경우엔 적합하지 않겠죠 ( 아키텍처 가이드(관심사 분리) 참조)

   3) UI Controller에 데이터 저장 및 복원 ▶️ 메모리 부족과 같은 시스템 이슈로 언제든 제거가 가능해 적합하지 않습니다

 

위와 같은 문제점을 해결하기 위해 ViewModel이 등장했습니다 

 

 

Repository

- ViewModel이 비즈니스 로직에 집중하기 위해 데이터의 초기화 및 데이터에 직접 접근을 하는 클래스 

즉, API 호출 및 Response 전달을 Repository에서 한다고 생각하면 됩니다 (데이터 통신을 담당)

- 모듈화 명확, 유지보수 용이

 

 

LiveData

- AAC의 일부, LifeCycle을 인식하며 관찰 가능한 데이터 홀더 클래스

- LifecycleOwner(Activity 혹은 Fragment)와 연결해야 합니다 

- LiveData 객체 내의 데이터에 액세스하려면 value 속성을 사용합니다

 

val currentData : MutableLiveData<String>
	get() = _currentData

fun getNextWord() {
	_currentData.value = String(텍스트)
}

fun setNextWord(str: String) {
	_currentData.postValue(str)
}

 

 


 

📣 MVVM 구현하기

 

1. ViewModel  클래스 생성

다른 클래스에서 데이터를 수정하면 안되기 때문에 private으로 선언

만약, 외부에서 데이터를 읽을 수 있어야 한다면 public val로 선언

 

class MainViewModel(val repository: MainRepository): ViewModel() {

    val _currentData: MutableLiveData<List<String>>
    
}

 

 

2. Repository  생성

API를 호출하고, ViewModel로 데이터를 전달합니다

(예제에선 Dagger를 통해 Rest API를 주입받습니다)

 

class MainRepository {
    @Inject
    lateinit var api: MainAPI
    
    var _currentData: MutableLiveData<List<String>>

	fun getList() {
    	//api에서 데이터를 가져오는 함수
        _currentData = api에서 가져온 데이터
    }

	fun sendList() : MutableLiveData<List<String>> {
    	return _currentData
    }
}

 

 

 

3. ViewModel 객체 생성

ViewModel 객체의 생성은 크게 2가지 방법으로 나뉩니다 

ViewModelProviders를 사용은 Deprecated 되었으므로, ViewModelProvider를 사용하겠습니다

 

1) 인자가 없는 경우

  - ViewModelProvider로 ViewModel 객체 생성

viewModel = ViewModelProvider(this).get(뷰모델클래스명::class.java)

 

  - ViewModelProvider(ViewModelStoreOwner)

  - Activity와 Fragment는 ViewModelStoreOwner를 포함하므로 this를 넣습니다 

 

2) 인자가 있는 경우

  - ViewModelProvider(ViewModelStoreOwner, ViewModelProvider.Factory)로 객체 생성

  - 인자가 있을 경우는, ViewModelProvider에 해당 객체를 생성할 수 있는 방법을 제공해야 합니다.

  - ViewModelProvider에 객체 생성 방법을 제공하기 위해 ViewModel 라이브러리에서         ViewModelProvider.Factory를 제공합니다

 

 

[ViewModelProvider.Factory 생성]

 

class MainViewModelFactory(val repository: MainRepository): ViewModelProvider.Factory {

   override fun <T: ViewModel?> create(modelClass: Class<T>: T {
   
	return modelClass.getConstructor(MainRepository::class.java).newInstance(repository)

	}
}

 

  - 생성된 팩토리를 ViewModelProvider의 인자로 설정해줍니다

val factory = MainViewModelFactory(repository)

val viewModel = ViewModelProviders.of(this, factory).get(뷰모델클래스명::class.java)

 

 

 

4. ViewModel에서 Repository 가져오기

 

class MainViewModel(val repository: MainRepository): ViewModel() {

    val _currentData: MutableLiveData<List<String>>
    
    fun getCurrentData() : MutableLiveData<List<String>> {
    	return repository().getCurrent()
    }
}

 

선언된 LiveData와 Repository에서 가져오는 값을 연결하려면 Repository에서 반환하는 함수를 연결해주면 됩니다 ! 

 

 fun getCurrentData() : MutableLiveData<List<String>> {
    	return repository().getCurrent()
    }

 

 

그렇다면, ViewModel에서 선언된 Reponse를 반환하는 함수는 어떻게 활용할까요? 

 

바로 UI Controller에서 사용하면 됩니다 ! 

 

5. View에서 ViewModel 사용하기 

 

ViewModel에서 데이터를 반환하는 

viewModel.getCurrentData.observe(lifeCycleOwner, { data->
   binding.tvTxt.text = data[0]
})

 

observe에 의해, update와 관련된 메서드 없이 LiveData Observe에서 자동으로 업데이트 됩니다 👍🏻

 

 

 


궁금하신 점이나 의견이 있으시면 댓글 부탁드립니다 감사합니다 😊

 

 

https://github.com/eunie9498

 

eunie9498 - Overview

Android Developer. eunie9498 has 9 repositories available. Follow their code on GitHub.

github.com

 

'📱 Android' 카테고리의 다른 글

[Android] 4대 Component  (0) 2022.07.05
[Android] Activity LifeCycle 🧐  (0) 2022.07.03
[Android] Jetpack Architecture #1 DataBinding  (0) 2022.06.05
[Android] Pattern (MVC, MVP, MVVM)  (0) 2022.05.30
[Android] Clean Architecture in Android  (0) 2022.05.29