안드로이드 26) MVVM 모델

MVVM 모델

1. Android MVVM

  • MVVM : AAC의 핵심 아키텍처
    • M(Model) : 업무로직에 의해 데이터가 발생되거나 데이터를 관리하는 부분
    • V(View) : 화면
    • VM(ViewModel) : Model과 View를 분리시키기 위한 역할자
    • View가 ViewModel을 실행시키면 ViewModel이 업무가 진행되는 Model을 실행시키고, Model에 의한 결과를 ViewModel이 받아 View에서 이용
  • 어플리케이션은 Separation of concerns에 의해 작성되는 것이 권장된다
    • 그로 인해 UI와 모델이 분리

2. AAC의 핵심 요소를 사용해서 개발시 전체적인 구조

1) Activity / Fragment : View

  • UI를 구성하고 유저와 상호 작용, LifeCycle 변경을 감지
  • LifeCycle 변경이 발생하면 ViewModel에 전달
  • ViewModel에서 전달한 LiveData의 내용을 화면에 출력
    • Activity나 Fragment에 가장 중요한 업무 로직은 이벤트를 처리인데 서버 데이터를 받다 보면 시간이 걸릴 수 있음
    • 이를 해결하기 위해 ViewModel에 요청해서 업무로직이 실행된 결과값을 LiveData로 받아내자

2) ViewModel : View와 Model을 분리

  • View와 Model을 분리시키기 위한 가교 역할
  • View의 LifeCycle 변경을 감지하고 변경이 발생하면 적절한 Repository를 실행시켜 업무가 진행되도록 함
  • Repository에서 발생한 LiveData를 View에 전달

3) Repository : 데이터 처리

  • 데이터의 저장 및 획득이 주 목적
    • Repository가 서버(WebServices)인 경우 Repository에 Retrofit 코드 작성
    • Repository가 DB인 경우 Room 이용

ViewModel

1. ViewModel

  • MVVM의 핵심은 화면에서 비즈니스 업무 로직을 분리해서 개발하는 것
  • Activity, Fragment에서 UI를 처리하고 ViewModel에서 비즈니스 업무 로직을 처리
  • Activity에서 onSaveInstanceState() 함수를 이용해 작성하는 Bundle 데이터 저장도 ViewModel로 대체가 가능

2. ViewModel 사용 방법
1) build.gradle 추가

implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'

2) ViewModel 상속으로 작성

class MyViewModel: ViewModel() {
    val user: MutableLiveData<User>
        get() {
            val user = MutableLiveData<User>()
            user.postValue(User("gildong", "hong1"))
            return user
        }
}

3) Activity에서 ViewModel 이용

val model = ViewModelProvider(this).get(MyViewModel::class.java)
model.user.observe(this, {
    binding.textView.text = "${it.firstName} - ${it.lasgName}"
})
  • ViewModelProvider를 이용한 객체 생성하고 ViewModel의 함수를 호출
  • 직접 객체 생성도 가능(비추천, Bundle 데이터 저장이 불가)
  • ViewModelProvider을 이용한 객체를 생성해야 Activity 상태 변화에 따른 ViewModel이 재생성되는 것을 막고, 데이터를 유지할 수 있음
implementation "androidx.activity:activity-ktx:$activity_version"
val model: MyViewModel by viewModels()
  • ViewModelProvider를 이용해 객체를 생성하는 것을 단순화 시킨 delegator

3. ViewModel Lifecycle

  • Activity가 상태 변화할 때, ViewModel은 종료되지 않아 데이터를 유지하고 ViewModel이 재생성되는 것을 막을 수 있다
  • Activity가 최종 종료 되면 ViewModel도 종료
  • Activity Scopte 내에서 Singleton

4. AndroidViewModel

  • AndroidViewModel은 ViewModel의 서브 클래스
  • ViewModel 내에서 application 객체를 이용하고자 할 때 AndroidViewModel 상속 받아서 사용
    • ViewModel()
    • AndroidViewModel(Application application)

5. Fragment에서 ViewModel 이용

  • Activity 내에 Fragment가 여러 개 있는 경우 Lifecycle Owner를 누구에게 주는가에 따라
    • 각 Fragment가 각각의 ViewModel을 가져 Fragment와 ViewModel의 Lifecycle이 같이 가게 할 수도 있고
    • Fragment간 ViewModel 공유할 수도 있다
val model = ViewModelProvider(requireActivity()).get(MyFragmentViewModel::class.java)
  • Fragment간에 ViewModel을 공유하게 할 경우 함수의 매개변수에 Activity를 주어 ViewModel의 Owner를 Activity로 변경

LiveData

1. LiveData

class MyViewModel: ViewModel() {
    // String 데이터 리턴, 뷰가 결과값이 넘어올 때까지 대기 상태에 빠짐
    fun someData(): String {
        return "hello"
    }
    // livedata 리턴, 비동기적으로 데이터를 받을 수 있음
    fun someData2(): MutableLiveData<String> {
        val liveData = MutableLiveData<String>()
        thread {
            SystemClock.sleep(3000)
            liveData.postValue("world")
        }
        return liveData
    }
}
  • ViewModel의 결과
  • ViewModel에서 String 등의 결과를 리턴시킬 수도 있지만 LiveData를 리턴 시켜 Observer로 결과 이용

2. Observer

val observer = object : Observer<String> {
    override fun onChanged(t: String?) {
        Log.d("min", "onChanged... $t")
    }
}
model.someData2().observe(this, observer)
val liveData = model.someData2()
...
liveData.removeObservers(this)
  • LiveData의 변경을 감지하는 observer는 Observer를 구현한 클래스
  • LiveData의 값이 변경되면 Observer의 onChanged() 함수가 자동 호출
  • 더 이상 감지가 필요 없는 경우 명시적으로 removeObservers 함수 호출

3. Custom LiveData

class MyLiveData: LiveData<String>() {
    fun sayHello(name: String) {
        postValue("Hello $name")
    }
}
val liveData1 = MyLiveData()
liveData1.observe(this) {
    Log.d("min", "result : $it")
}
liveData1.sayHello("min")
  • LiveData를 상속받아 작성
  • ViewModel 이외에 다른 곳에서 사용 가능

좋은 웹페이지 즐겨찾기