개요
ViewModel 클래스는 수명 주기를 고려해 UI와 관련된 데이터를 저장하고 관리한다.
ViewModel 클래스를 사용하면 화면 회전과 같은 인스턴스 제거 → 재생성 과정을 거쳐도 데이터를 유지할 수 있다.
꼭 ViewModel로 데이터를 유지시키지 않아도 대안은 있긴 하다.
예를 들면 앱의 Activity들 중 하나에 사용자 목록이 포함되어 있는데, 구성이 변경되어 Activity가 다시 생성되면 새 Activity가 사용자 목록을 다시 가져와야 하는데,
데이터가 단순한 경우 Activity의 onSaveInstanceState() 메소드를 사용하여 onCreate()의 번들에서 데이터를 복원할 수 있다.
하지만 이 방법은 사용자 목록이나 비트맵과 같은 대용량의 데이터가 아니라, 직렬화했다가 다시 역직렬 화할 수 있는 소량의 데이터에만 적합하다.
다른 문제로는 UI 컨트롤러가 반환하는 데 시간이 걸릴 수 있는 비동기 호출을 자주 해줘야 한다.
UI 컨트롤러는 비동기 호출을 관리해야 하고, 메모리 누수 가능성을 방지하기 위해 호출이 제거된 후 시스템에서 호출을 정리하는지 확인해야 한다.
관리에는 많은 비용이 따르고, 구성 변경 시 개체가 다시 생성되는 경우 개체가 이미 수행된 호출을 또 호출해야 할 수 있으므로 리소스가 낭비되게 된다.
따라서 UI 컨트롤러 로직에서 뷰 데이터 소유권을 분리하기 위해 ViewModel을 사용하는 것이 쉽고 효율적이다.
구현
AAC는 UI의 데이터 준비를 담당하는 UI 컨트롤러에 ViewModel이라는 도우미 클래스를 제공한다.
ViewModel의 객체는 구성이 변경되는 동안 자동 보관되므로 포함하고 있는 데이터는 Activity 또는 Fragment 인스턴스에서 즉시 사용할 수 있다.
MyViewModel.kt
class MyViewModel : ViewModel() {
private val users: MutableLiveData<List<User>> by lazy {
MutableLiveData().also {
loadUsers()
}
}
fun getUsers(): LiveData<List<User>> {
return users
}
private fun loadUsers() {
// 비동기 작업 수행
}
}
MainActivity.kt
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val model: MyViewModel by viewModels()
model.getUsers().observe(this, Observer<List<User>>{ users ->
// users 데이터로 UI 업데이트 수행
})
}
}
MainActivity가 다시 생성되더라도 맨 처음 생성된 동일한 MyViewModel의 인스턴스가 유지된다.
해당 Activity 또는 Fragment가 완전히 종료되면 안드로이드 프레임워크는 리소스를 정리하기 위해 ViewModel 객체의 onCleared() 메서드를 호출한다.
참고로 Fragment의 경우는 해당 Fragment가 분리될 때까지 메모리에 남아있는다.
좀 더 쉽게 이해하기 위해서 아래 이미지를 참고하면 도움이 될 것 같다.
마지막으로 ViewModel은 View, Lifecycle, Activity Context를 받아도 안되고, 포함하는 클래스를 참조하면 안 된다!!
'Android' 카테고리의 다른 글
[Android] Mac M1 Room 라이브러리 에러 (0) | 2021.07.30 |
---|---|
[안드로이드] Android Architecture Components(AAC)의 LiveData (0) | 2021.03.18 |
[안드로이드] Module 수준의 Gradle (0) | 2021.03.18 |
[안드로이드] Room (0) | 2021.03.17 |
[안드로이드] MVC, MVP, MVVM 아키텍처 패턴 (0) | 2021.03.17 |