[안드로이드] View Model

2021. 2. 5. 11:12카테고리 없음

View Model

View Model이란 MVVM(Model + View + View Model)이라는 개발 디자인 패턴에서 View Model에서 나온 패턴 방식이다. View Model클래스는 주로 수명 주기를 고려하여 UI관련 데이터를 저장하고 관리하도록 설계되어 있습니다. 

 

View Model 클래스를 사용하면 화면 회전과 같이 구성을 변경할 때도 데이터를 유지할 수 있습니다. 

 

안드로이드에서 사용하는 View Model은 ACC View Model로 일반적인 ViewModel이랑은 다르다. 

 

ACC View Model은 화면 회전시에 데이터를 유지할 수 있게 만들어 주는 View Model이다. 

 

View Model 사용 이유

View Model은 View로 부터 독립적이며 View가 필요로 하는 데이터를 가지고 있는 클래스를 의미한다. 이렇게 데이터와 실질적인 UI를 구분시켜서 Activity, Fragment와 같은 UI에 과도한 책임이 발생하는 걸 방지하고 클래스가 거대해지는 것을 방지한다. 

 

 즉 재사용성, 유지보수 등을 유용하게 해줄 수 있다. 

 

View Model Life Cycle

프래그먼트에서도 동일

View Model은 범위가 지정된 Life Cycle이 영구적으로 경과될 때 까지, 즉 Activity에서는 Activity가 종료될 때 까지 프래그먼트에서는 프래그먼트가 분리될 때 까지 메모리에 영구적으로 남아있습니다. 

 

일반적으로는 OnCreate 함수가 호출될 때 View Model 객체가 호출됩니다. 그리고 Activity가 완전히 종료가 되면 메모리에서 사라집니다. 

 

View Model 사용하기

 

View Model 구현

class MyViewModel : ViewModel() {
    private val users: MutableLiveData<List<User>> by lazy {
        MutableLiveData().also {
            loadUsers()
        }
    }

    fun getUsers(): LiveData<List<User>> {
        return users
    }

    private fun loadUsers() {
        // Do an asynchronous operation to fetch users.
    }
}

 

View Model에 접근하기

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
        })
    }
}

 

View Model Factory

일반적으로 View Model을 사용할 때 파라미터를 넘겨주지 않고 사용하는 경우는 거의 없다. 그래서 우리는 ViewModel Factory를 사용하여 원하는 데이터를 전달해줄 때 사용하면 된다. 

 

기존의 View Model 위의 예제랑 다르게 final Score를 받는 인자가 없다. 

class ScoreViewModel(finalScore: Int) : ViewModel() {
   // The final score
   var score = finalScore
   init {
       Log.i("ScoreViewModel", "Final score is $finalScore")
   }
}

 

View Model Factory

class ScoreViewModelFactory(private val finalScore: Int) : ViewModelProvider.Factory {
  override fun <T : ViewModel?> create(modelClass: Class<T>): T {
   if (modelClass.isAssignableFrom(ScoreViewModel::class.java)) {
       return ScoreViewModel(finalScore) as T
   }
   throw IllegalArgumentException("Unknown ViewModel class")
 }
}