https://developer.android.com/topic/libraries/architecture/viewmodel 에 잘 설명되어 있다.
ViewModel 를 사용하는 가장 큰 이유는 UI 와 로직의 분리이다.
액티비티, 프래그먼트 생명주기에 종속되지 않게 할 수 있다는 점이 가장 큰 매력이다.
실행되는 앱을 가로모드, 세로모드로 변경하면 값이 초기화되는데 ViewModel 을 사용하면 값이 유지된다.
ViewModel에는 onCleared() 함수가 존재한다.
jetpack LiveData
Observer에게 데이터 변경에 대한 알림을 보내는 클래스이다.
계속해서 데이터를 관찰하고 업데이트되기 때문에 UI 와 데이터간에 일치성을 가진다는 장점을 가지고 있다.
ViewModel 에서 context나 activity객체를 사용하고 싶다면 AndroidViewModel() 사용해야 한다.
여러 유투브 동영상을 보고 "개발하는 정대리" https://www.youtube.com/watch?v=-b0VNKw_niY 강좌가 간단하면서도 개념 이해하는데 도움이 되는 거 같아서 이걸 보면서 연습한 코드를 적어둔다.
동영상 강좌 중에 ViewModelProvieders.of(this).get(~~) 이런식으로 설명한 코드가 있는데 테스트 해보니
ViewModelProviders는 deprecated 되었더라. 그러므로 ViewModelProvider를 사용해줘야 한다.
앱 build.gradle 추가사항
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
android {
buildFeatures { // 뷰 바인딩 사용하겠다.
viewBinding true
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
// 뷰모델 (ViewModel)
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
// 라이브 데이터(LiveData) - 옵저버 패턴 관련 - 데이터의 변경 사항을 알 수 있다.
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
}
|
MainViewModel.kt
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
38
39
40
41
42
43
44
|
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
enum class ActionType {
PLUS, MINUS
}
// 데이터의 변경 : 뷰모델은 데이터의 변경 사항을 알려주는 라이브 데이터를 가지고 있음
class MainViewModel : ViewModel() {
companion object{
const val TAG: String = "로그"
}
// 뮤터블 라이브 데이터 - 수정 가능
// 라이브 데이터 - 값 변경 안됨
// 내부에서 설정하는 자료형은 뮤터블로 변경가능하도록 설정
private val _currentValue = MutableLiveData<Int>()
// 변경되지 않는 데이터를 가져올 때 이름을 _언더스코어 없이 설정
// 공개적으로 가져오는 변수는 private 이 아닌 public으로 외부에서도 접근 가능하도록 설정
// 하지만 값을 직접 라이브데이터에 접근하지 않고 뷰모델을 통해 가져올 수 있도록 설정
val currentValue: LiveData<Int>
get() = _currentValue
// 초기값 설정
init {
Log.d(TAG, " MainViewModel - 생성자 호출")
_currentValue.value = 0
}
fun updateValue(actionType: ActionType, input: Int){
when(actionType){
ActionType.PLUS ->
_currentValue.value = _currentValue.value?.plus(input)
ActionType.MINUS ->
_currentValue.value = _currentValue.value?.minus(input)
}
}
}
|
MainActivity.kt
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
38
39
40
41
42
43
|
class MainActivity : AppCompatActivity(), View.OnClickListener {
companion object{
const val TAG: String = "로그"
}
val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
// 나중에 값이 설정될 것이라고 lateinit 으로 설정
lateinit var mainViewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//setContentView(R.layout.activity_main)
setContentView(binding.root) // View Bindg 과정
// 뷰 모델 프로바이더를 통해 뷰모델 가져오기
mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
// 뷰모델이 가지고 있는 값의 변경사항을 관찰할 수 있는 라이브 데이터를 관찰한다
mainViewModel.currentValue.observe(this, Observer {
Log.d(TAG,"MainActivity - mainViewModel - CurrentValue 라이브 데이터 값 변경 : $it")
binding.tvNumber.text = it.toString()
})
// 리스너 연결
binding.btnPlus.setOnClickListener(this)
binding.btnMinus.setOnClickListener(this)
}
override fun onClick(view: View?) {
val userInput: Int = binding.etNumber.text.toString().toInt()
// ViewModel 에 LiveData 값을 변경하는 메소드
when(view){
binding.btnPlus ->
mainViewModel.updateValue(actionType = ActionType.PLUS, userInput)
binding.btnMinus ->
mainViewModel.updateValue(actionType = ActionType.MINUS, userInput)
}
}
}
|
내 GitHub 에 올린 전체 소스 코드
https://github.com/jsk005/KotlinProjects/tree/master/viewmodel
'안드로이드 > Kotlin 기능' 카테고리의 다른 글
[코틀린] MPChart LineChart 예제 (라이브러리 2.2.5) (0) | 2021.06.14 |
---|---|
[코틀린] MPChart LineChart 예제 (라이브러리 3.1.0) (0) | 2021.06.14 |
코틀린 view binding (0) | 2021.06.03 |
[코틀린] 인터넷 IP 주소 알아내기 (0) | 2021.02.06 |
[코틀린] IP 주소 알아내기 (0) | 2021.02.06 |