반응형

이 게시물은 다음 링크를 참조하여 학습했습니다.

 

 

Android 아키텍처 구성요소  |  Android 개발자  |  Android Developers

앱 작업

developer.android.com

 

ViewModel 개요  |  Android 개발자  |  Android Developers

ViewModel을 사용하면 수명 주기를 인식하는 방식으로 UI 데이터를 관리할 수 있습니다.

developer.android.com

 

LiveData 개요  |  Android 개발자  |  Android Developers

LiveData를 사용하여 수명 주기를 인식하는 방식으로 데이터를 처리합니다.

developer.android.com

 

안드로이드 View Model(뷰 모델)을 공부해보자!

1. ViewModel  1-1. ViewModel 이란?  1-2. 탄생 배경  1-3. 사용하는 이유 2. 사용법  2-1. gradle 추가  2-2. Layout 파일  2-3. ViewModel 파일  2-4. Activity 파일 3. 주의할 점  3-1. 참조 1. View..

todaycode.tistory.com

 

LiveData(라이브 데이터)란?

1. LiveData란?  1-1. Observer  1-2. LiveData  1-3. LiveData의 장점 2. 사용법  2-1. gradle  2-2. LiveData 객체 생성  2-3. Observer 객체 생성 3. 예제 4. 더 알아보기  3-1. LifeCycleOwner  3-2...

todaycode.tistory.com

 

LiveData 와 MutableLiveData

MutableLiveData는 Abstract Class 인 LiveData를 구현한 Public Class 위 말을 풀어 보면, 1. LiveData는 추상 클래스이므로 직접 생성할 수 없다. public abstract class LiveData { protected void postValue(..

comoi.io

이번 게시물은 View Model, Live Data에 대한 내용이다.

MVVM패턴을 사용해보려 했는데, View Model 이라는 생소한 개념이 나와서 View Model이 뭔지 알아보려고 View Binding, Data Binding 부터 해서 여기까지 왔다.....

처음에 View Model을 들었을 때는 MVC 패턴에서 우리가 사용하는 Activity를 Controller라고 하는 것처럼 '다른 무언가'를 View Model이라고 하는줄 알았는데 아니였다.

 

1-1. View Model

일반적으로 코딩을 할 때 액티비티의 onCreate() 메서드 안에서 여러가지 데이터에 대한 초기화 작업을 해준다.

그런데, 만약에 어플의 화면이 가로 모드로 회전되거나 데이터가 바뀌면 안되는 상황에서 의도치 않게 onCreate() 메서드가 새로 호출된다면 데이터가 의도치 않게 초기화되는 불상사가 발생할 것이다.

안드로이드 공식문서에서는 saveInstanceState를 통해 데이터를 복원할 수 있지만, 크기가 작은 데이터에서만 사용하기를 권장한다. 

즉, List나 Bitmap같이 용량이 커질 수 있는 데이터는 saveInstanceState를 사용할 수 없다.

 

액티비티나 프래그먼트에서 데이터를 관리하려고 하니 생명주기에 따라서 값이 사라지고, saveInstanceState를 사용하자니 용량이 큰 데이터를 저장할 수 없다.

이를 해결하기 위해 나온게 ViewModel이다.

안드로이드는 '강력하고 테스트와 유지관리가 쉬운 앱을 디자인하도록 돕는 라이브러리 모음'을 제공하는데, 이것이 AAC(Android Architecture Component)이고, ViewModel은 AAC중 하나이다.

 

좀전에 위에서 '생명주기'에 관한 이야기를 했는데, ViewModel은 액티비티 또는 프래그먼트와 다른 생명주기를 갖는다.

ViewModel의 생명주기

즉 ViewModel을 사용하면 Activity, Fragment에서의 UI 수정작업을 독립시켜서 작업량을 줄여줄 수 있고, 

유지보수, 재사용성, 테스트등을 용이하게 만들어준다.

이런 ViewModel을 사용하기 전에 우리는 LiveData라는 녀석을 알고 가야한다.

 

1-2. LiveData

1-2-1. Observer

Observer의 사전적 정의는 '관찰자' or '감시자' 이다.

안드로이드에서의 Observer는 데이터의 변경을 계속 관찰하면서 변화가 있을 때 컨트롤러(Activity)에 전달하는 역할을 한다.

이 Observer를 사용하면 데이터의 변화를 실시간으로 관찰해서 다른 작업들을 할 수 있는데,

LiveData라는 데이터 홀더 클래스가 갖고 있는 데이터만 관찰할 수 있다.

 

1-2-2. LiveData

LiveData를 사용할 때는 LiveData, MutableLiveData 두가지 클래스를 사용한다.

MutableLiveData는 단어 뜻대로 변경 가능한 라이브 데이터이다.

그리고 LiveData는 값의 변경이 불가능하다.

LiveData가 값이 변경 불가능하다면, 왜 LiveData, MutableLiveData 두가지 클래스를 사용할까....?

 

먼저 짚고 넘어가야 할 점은 MutableLiveData는 추상클래스인 LiveData를 상속받은 클래스이다.

즉, LiveData는 추상클래스이므로 직접 생성이 불가능하다.

1
2
3
4
1. val data : LiveData<String> = repository.getData() 
//Room에서 생성한 LiveData를 직접 할당
2. val dataMutable = MutableLiveData<String>() val name : LiveData<String> = dataMutable
MutableLiveData를 생성해서 LiveData로 넘겨줌 
cs

위와 같은 방법을 통해서만 값을 설정 가능하다.

 

ViewModel 관점에서 봤을 때 데이터를 Front로 제공할 때는 수정이 불가능한 LiveData를 제공해야 하고, 데이터를 수정할 때 MutableLiveData를 사용한다 생각하면 된다.

데이터를 수정할 때는 ViewModel내에서 1) Room을 사용한다면 Room의 바뀐 데이터를 LiveData로 업데이트 해주고, 2) Room을 사용하지 않는다면 ViewModel 내의 MutableLiveData를 LiveData와 연결한 후 수정해주면 된다.

 

2. 사용법

2-1. gradle 추가

프로젝트 수준 gradle( build.gradle(Project: 프로젝트명) )에서 다음 항목을 추가 시켜준다.

기본적으로 프로젝트를 생성하면 똑같이 생성되긴 하는데, 꼭 확인해주자!

1
2
3
4
5
6
allprojects {
    repositories {
        google() // 이 부분
        jcenter()
    }
}

그 다음, 모듈 수준 gradle( build.gradle(Module: 프로젝트명) )에서 다음 항목을 추가 시켜준다.

1
2
3
4
5
6
7
dependencies {
    def lifecycle_version = "최신버전"
    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
}
cs

최신 버전은 아래 링크에서 확인할 수 있다.

 

Lifecycle  |  Android 개발자  |  Android Developers

Lifecycle 수명 주기 인식 구성요소는 활동 및 프래그먼트와 같은 다른 구성요소의 수명 주기 상태 변경에 따라 작업을 실행합니다. 이러한 구성요소를 사용하면 잘 구성된 경량의 코드를 만들어

developer.android.com

 

2-2. ViewModel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class MyViewModel : ViewModel() {
    private val users: MutableLiveData<List<User>> by lazy {
        MutableLiveData<List<User>>().also {
            loadUsers()
        }
    }
 
    fun getUsers(): LiveData<List<User>> {
        return users
    }
 
    private fun loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}
cs

안드로이드 공식 문서에서 제공하는 간단한 ViewModel 구현 예제이다.

위에서 설명했던 것처럼 MutableLiveData를 생성하고, 제공할 때 LiveData형태의 데이터를 반환하는 모습을 볼 수 있다.

 

2-3. Activity에서의 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyActivity : AppCompatActivity() {
 
    override fun onCreate(savedInstanceState: Bundle?) {
        // Create a ViewModel the first time the system calls an activity's onCreate() method.
        // Re-created activities receive the same MyViewModel instance created by the first activity.
 
        // Use the 'by viewModels()' Kotlin property delegate
        // from the activity-ktx artifact
        val model: MyViewModel by viewModels()
        model.getUsers().observe(this, Observer<List<User>>{ users ->
            // update UI
        })
    }
}
cs

Observe는 LiveData에서 말했던 Observer를 생각하면 된다.

ViewModel에서의 데이터를 getUsers()를 통해 받아오고, 이 받아온 데이터가 변화가 있는지 observe()메서드를 통해 확인한다고 이해하면 된다.

 

2-4. Fragment에서의 사용

하나의 액티비티에 둘 이상의 프래그먼트를 사용할 때, 같은 ViewModel을 사용해서 데이터를 공유할 수 있다.

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
31
32
33
34
35
36
37
class SharedViewModel : ViewModel() {
    val selected = MutableLiveData<Item>()
 
    fun select(item: Item) {
        selected.value = item
    }
}
 
class ListFragment : Fragment() {
 
    private lateinit var itemSelector: Selector
 
    // Use the 'by activityViewModels()' Kotlin property delegate
    // from the fragment-ktx artifact
    private val model: SharedViewModel by activityViewModels()
 
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        itemSelector.setOnClickListener { item ->
            // Update the UI
        }
    }
}
 
class DetailFragment : Fragment() {
 
    // Use the 'by activityViewModels()' Kotlin property delegate
    // from the fragment-ktx artifact
    private val model: SharedViewModel by activityViewModels()
 
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        model.selected.observe(viewLifecycleOwner, Observer<Item> { item ->
            // Update the UI
        })
    }
}
cs

지금은 하나의 페이지에 다같이 코딩했지만, 실제로는 각각 다른 클래스 파일이라고 봐도 된다.

ViewModel을 각각의 프래그먼트에서 생성하는데, 액티비티에서 by viewModels()로 생성한 것과 다르게

프래그먼트에서는 by activityViewModels()로 생성하고 똑같이 사용하면 된다.

 

** 주의사항!!

ViewModel은 View, LifeCycle 또는 Activity Context를 참조하는 클래스를 참조하면 안된다.

처음에 설명했듯이 ViewModel은 독자적인 LifeCycle( 더 긴 )을 갖고 있기 때문에, 메모리 누수가 발생할 수 있다고 한다.

단 Application Context는 어플리케이션 생명주기를 갖기 때문에 참조해도 괜찮다고 한다.

반응형

+ Recent posts