일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- 안드로이드 클린 아키텍처
- Koin
- coroutine
- android clean architecture
- 안드로이드 테스트코드
- 안드로이드 Espresso
- android memory leak
- 안드로이드 리싸이클러뷰
- sharedFlow
- 안드로이드 hilt
- 안드로이드 앱 아키텍처 가이드라인
- 리싸이클러뷰 최적화
- 안드로이드 mvvm예제
- 안드로이드 앱 아키텍처 가이드라인 사용법
- Android App Architecture Guideline
- android DI
- 안드로이드 앱 아키텍처 가이드라인 설명
- 안드로이드 의존성주입
- 안드로이드 아키텍처 컴포넌트
- 안드로이드 JUnit
- Hilt
- 스타트업 코딩테스트
- 안드로이드 최적화
- MVVM
- Android MVVM
- RxJava
- 안드로이드 앱 아키텍처 가이드라인 예시
- 안드로이드 mvvm
- 코루틴
- 안드로이드 Mockito
- Today
- Total
안드로이드 연구소
[MVVM만들기] ViewModel + LiveData 본문
오늘은 드디어 MVVM패턴을 가진 샘플 파일을 만들어보겠습니다.
그때 필요한 안드로이드 아키텍처 컴포넌트(줄여서 AAC)는 바로 ViewModel + LiveData + DataBinding.
각 각 어떤 역할을 하는지 살펴보고 어떻게 사용할 수 있는지 알아보겠습니다.
바로 시작!
Q1. AAC의 구성요소인 ViewModel에 설명해줘
ViewModel 구성요소는 수명 주기를 인식하는 방식으로 UI 관련 데이터를 저장하고 관리하도록 설계되었습니다.
이를 통해 UI 로직에서 데이터 관리를 분리할 수 있으므로 코드를 보다 체계적이고 유지 관리 및 테스트할 수 있습니다.
화면 회전과 같은 구성 변경을 유지하도록 특별히 설계되었으며 엑티비티 또는 프래그먼트의 수명 주기에 연결되어 있습니다.
ViewModel은 자신을 사용하는 UI 구성 요소에 대한 직접적인 관여하지 않습니다.
LiveData처럼 관찰 가능한 개체를 통해 데이터를 노출하며, UI 구성 요소는 필요에 따라 이를 관찰하고 업데이트할 수 있습니다.
ViewModel은 첫번째 데이터를 저장하는 핵심 기능으로 보입니다.
기존의 UI업데이트를 담당하는 기능에서 데이터만 쏙 가져와서 ViewModel에 저장해놓는다고 생각하면 편하겠는네요.
또 다른 두번째 특징으로는 ViewModel에 데이터를 저장해두면
화면 회전에서 데이터를 초기화시키는 문제를 해결할 수 있는 것으로 보입니다.
애플리케이션에서 configuration change(ex, 화면회전) 발생할 때마다
세로형태의 엑티비티가 Destory되고 다시 가로형태의 엑티비티가 Create되었습니다.
그래서 화면을 그리고 있던 UI 데이터가 유지되지 않고 초기화 되는 현상들이 일어났습니다.
이를 해결한게 ViewModel라이브러리이네요.
마지막 세번째 특징으로는 ViewModel이 직접 UI업데이트에 관여하지 않습니다.
LiveData라이브러리의 기능의 도움으로 UI 새로 업데이트하는 것으로 보입니다.
서로 공존 관계처럼 보이네요.
약간 이상한점이 보이는데 MVVM의 모델-뷰-뷰모델의 ViewModel과
지금 배운 안드로이드 아키텍처 컴포넌트의 ViewModel은 다른걸까요?
Q2. MVVM의 뷰모델과 AAC의 ViewModel은 다른거야?
네, 둘은 다른 서로 다른 요소입니다.
비슷한 개념이지만 관점과 사용법에서 다릅니다.
MVVM의 뷰모델은
안드로이드에서 뿐만 아니라 다양한 개발에서 사용되는 디자인 패턴 중 하나이고
모델과 상호 작용하여 데이터를 검색 및 조작하고 관찰 가능한 속성을 사용하여 필요한 데이터를 보기에 노출합니다.
즉, 데이터를 View에 노출하고 비즈니스 로직을 포함하는 역할을 합니다.
AAC의 ViewModel은
안드로이드에서 사용되는 라이브러리로써 기존의 안드로이드에서 가지고 있던 문제들을 해결하기위해 탄생하였다.
UI 구성요소(데이터베이스 또는 네트워크 호출에서 검색된 데이터)에 필요한 데이터를 저장한다.
또 구성 변경(화면 회전) 시 데이터가 유지되도록 한다.
간단히 말하면
MVVM의 뷰모델은 (많은 개발에서도 사용하고 있는 디자인 패턴의 일부중 하나로) 데이터를 View로 노출하는 관점에서 봐야하고
AAC의 ViewModel는 (안드로이드 라이브러리 중 하나로) 데이터를 저장하고 화면회전시 데이터를 초기화시킨 문제를 해결한 역할을 한 도구로써의 관점으로 서로를 이해해주어야겠네요.
Q3. 그렇다면 ViewModel 이전에는 어떻게 사용하였었니?
onSaveInstanceState() 메서드를 사용하여
화면 회전과 같은 구성 변경으로 인해 Activity가 소멸되었을 때 UI 관련 데이터를 저장했습니다.
하지만 이 메서드는 많은 양의 데이터를 저장하는 데 적합하지 않습니다.
또한 경우에 따라 Bundle 개체가 손실되거나 손상되어 중요한 데이터가 손실될 수 있습니다.
이를 해결하기 위해 SharedPreferences와 같은 다른 기술을 사용하거나
복잡하고 오류가 발생하기 쉬운 데이터베이스에 데이터를 저장해야 했습니다.
안드로이드 개발자들은 많은 양의 데이터를 저장할 수 있으면서
엑티비티나 프레그먼트가 파괴되고 다시 생성되더라도 데이터가 유지되도록 하는 기능이 필요로 하였습니다.
onSaveInstanceState() 메서드를 사용하였지만 큰 데이터들을 관리할 수 가 없었고
sharedPreferences라는 저장 방법을 사용하였지만 엑티비티의 데이터를 화면 하나씩 관리하기에는 효율적이지 못했습니다.
이렇게 하여 AAC의 viewModel이 나오게된 배경이 되었습니다.
Q4. ViewModel 사용방법?
build.gradle에서 호출
dependencies {
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
}
Activity의 데이터를 따로 관리해줄 MyViewModel.kt파일을 생성한뒤
ViewModel()을 extends한다.
class MyViewModel : ViewModel() {
}
그리고 아래와 같은 엑티비티에서 ViewModelProvider를 사용하여
만들어준 MyViewModel의 인스턴스를 만들어주는 방법이 있습니다.
class MyActivity : AppCompatActivity() {
private lateinit var binding: ActivityMyBinding
private lateinit var myViewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMyBinding.inflate(layoutInflater)
setContentView(binding.root)
myViewModel = ViewModelProvider(this).get(MyViewModel::class.java)
}
}
근데 여러분들 이렇게 ViewModel 인스턴스를 만들면
onDestroy()될 때 마다 해당 인스턴스를 매번 정리해주지 않으면 메모리 누수가 발생한다고 합니다.
그래서 by ViewModels()함수를 사용하면 더 깔끔한 코드로 메모리 누수도 예방할 수 있답니다.
class MyActivity : AppCompatActivity() {
private lateinit var binding: ActivityMyBinding
private val myViewModel: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMyBinding.inflate(layoutInflater)
setContentView(binding.root)
}
}
끝! 엥? 너무 쉽죠?
그렇다면 이제 데이터를 가지고 어떻게 우리의 엑티비티 화면에 업데이트 할 수 있을까요?
아까 얘기했듯이 ViewModel은 LiveData와 공생하여 존재하고 있습니다.
그러면 이제는 LiveData에 대해 알아볼까요?
Q5. LiveData에 대해 설명해줘
LiveData는 관찰 가능한 데이터 홀더 클래스입니다.
데이터에 변경 사항이 있을 때 UI 구성 요소(엑티비티, 프래그먼트, 뷰)가 관찰자가 되어 변화를 알리는 데 사용됩니다.
LiveData는 관찰자(UI 구성 요소)가 최신 데이터로 항상 업데이트된 상태인지 확인합니다.
수명 주기를 인식하므로 활성 상태에 있는 UI 구성 요소만 업데이트합니다.
UI 컴포넌트 참조하지 않아 메모리 누수를 예방한다.
Q6. ViewModel을 사용한 예제에 LiveData를 사용시킨 예제를 보여줘!
dependencies {
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
}
예시로 name과 age를 담을 수 있는 object클래스를 우선 만들겠습니다.
데이터 클래스는 여러분들이 담야할 값들을 형태가 되겠죠?
data class User(val name: String, val age: Int)
그리고 MyViewModel.kt에서는
_mData는 MutableLiveData를 사용하여 LiveData전용 변수를 사용합니다.
그리고 updateUser()함수를 사용하여 데이터 변수를 업데이트하게 해주었습니다.
class MyViewModel : ViewModel() {
private val _userData = MutableLiveData<User>()
val userData: LiveData<User> = _userData
fun updateUser(newUser: User) {
_userData.value = newUser
}
}
그리고 만들어둔 MyActivity.kt에서
로직 1을 통해서 myViewModel의 userData를 변화를 관찰하게끔 세팅을 해줍니다.
로직 2를 통해서 name이 John이고 age가 25인 User 데이터를 ViewModel에 업데이트 해줍니다.
드디어 로직2를 통해서 바뀐 mData를 로직1에서 포착하여서 내부 로직3이 실행되어 UI가 업데이트됩니다.
class MyActivity : AppCompatActivity() {
private lateinit var binding: ActivityMyBinding
private val myViewModel: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMyBinding.inflate(layoutInflater)
setContentView(binding.root)
// 로직1: viewModel의 userData 관찰
myViewModel.userData.observe(this, { user ->
// 로직3: 새 데이터 변화 관측 시 UI업데이트
binding.nameTextView.text = user.name
binding.ageTextView.text = user.age.toString()
})
// 로직2: 새로운 데이터 입력
val newUser = User("John", 25)
myViewModel.updateUser(newUser)
}
}
이렇게 ViewModel에 저장된 데이터를 가지고
LiveData를 이용하여 관찰하여 Activity에서 그려주는 이 로직
이제 이해되시는가요?
그러면 오늘은 여기까지 감사합니다
'안드로이드 연구소 > MVVM+AAC' 카테고리의 다른 글
[MVVM만들기] Lifecycle (1) | 2023.05.15 |
---|---|
[MVVM만들기] http통신(Retrofit2) (0) | 2023.05.12 |
[MVVM만들기] DataBinding (0) | 2023.05.12 |
[안드로이드 개발 공식 가이드라인] 안드로이드 아키텍처 컴포넌트 (0) | 2023.05.11 |
[안드로이드 개발 공식 가이드라인] 왜 구글은 안드로이드에서 MVVM을 사랑하였는가? (0) | 2023.05.11 |