ViewModel 클래스는 수명 주기를 고려하여 UI 관련 데이터를 저장하고 관리하도록 설계되었습니다. ViewModel 클래스를 사용하면 화면 회전과 같이 구성을 변경할 때도 데이터를 유지할 수 있습니다.
위 그림을 보면 ViewModel의 사용으로 UI 컨트롤러의 생명주기로 부터 종속되지 않을 수 있습니다. 그래서 데이터의 사용이 더 쉬워집니다.
1. onSaveInstanceState() 메서드의 한계
시스템에서 UI 컨트롤러를 제거하거나 다시 만드는 경우, 컨트롤러에 저장된 모든 일시적인 UI 관련 데이터가 삭제됩니다. 데이터가 단순한 경우 활동은 onSaveInstanceState() 메서드를 사용하여 onCreate()의 번들에서 데이터를 복원할 수 있습니다. 하지만 이 접근 방법은 사용자 목록이나 비트맵과 같은 대용량일 가능성이 높은 데이터가 아니라, 직렬화했다가 다시 역직렬화할 수 있는 소량의 데이터에만 적합합니다.
2. 중복 호출로 방지 및 메모리 누수 방지에 유용
다른 문제는 UI 컨트롤러가 반환하는 데 시간이 걸릴 수 있는 비동기 호출을 자주 해야 한다는 점입니다. UI 컨트롤러는 비동기 호출을 관리해야 하며, 메모리 누수 가능성을 방지하기 위해 호출이 제거된 후 시스템에서 호출을 정리하는지 확인해야 합니다. 관리에는 많은 유지관리가 필요하며, 구성 변경 시 개체가 다시 생성되는 경우 개체가 이미 수행된 호출을 다시 호출해야 할 수 있으므로 리소스가 낭비됩니다.
3. 뷰 데이터 소유권을 분리
Activity 및 프래그먼트와 같은 UI 컨트롤러의 목적은 기본적으로 UI 데이터를 표시하거나, 사용자 작업에 반응하거나, 권한 요청과 같은 운영체제 커뮤니케이션을 처리하는 것입니다. 또한 UI 컨트롤러에 데이터베이스나 네트워크에서 데이터 로드를 책임지도록 요구하면 클래스가 팽창됩니다. UI 컨트롤러에 과도한 책임을 할당하면 다른 클래스로 작업이 위임되지 않고, 단일 클래스가 혼자서 앱의 작업을 모두 처리하려고 할 수 있습니다. 또한 이런 방법으로 UI 컨트롤러에 과도한 책임을 할당하면 테스트가 훨씬 더 어려워집니다. UI 컨트롤러 로직에서 뷰 데이터 소유권을 분리하는 방법이 훨씬 쉽고 효율적입니다.
1. MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
//ViewModel 사용 회전시 데이터 보존
val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
viewModel.getInputText().observe(this, Observer {
binding.resultText.text = it
})
binding.button.setOnClickListener {
viewModel.updateText(binding.editText.text.toString())
}
}
}
ViewModel 객체의 범위는 ViewModel을 가져올 때 ViewModelProvider에 전달되는 Lifecycle로 지정됩니다. ViewModel은 범위가 지정된 Lifecycle이 영구적으로 경과될 때까지, 즉 Activity에서는 Activity가 끝날 때까지 그리고 프래그먼트에서는 프래그먼트가 분리될 때까지 메모리에 남아 있습니다.
2. MainViewModel.kt
class MainViewModel : ViewModel() {
private var inputText: MutableLiveData<String> = MutableLiveData()
fun getInputText() = inputText
fun updateText(newText: String) {
inputText.value = newText
}
}
https://developer.android.com/topic/libraries/architecture/viewmodel?hl=ko