ViewModel 사용하기

2020. 8. 19. 16:50android

1. 개념 


viewModel은 기본적으로 UI관리를 별도로 하기 위해서 만들어졌습니다. 기존에 UI를 관리하기 위해서는 액티비티나 프래그먼트 등 복잡한 라이프 사이클에 따라서 알맞게 처리되어져야 했기 때문에 매우 복잡했던 것이죠.

또한 화면 회전이나 비정상적인 종료로 인한 UI상 정보를 저장하고 불러오는 일 또한 관리하기 힘들었습니다. 왜냐하면 bundle에 저장할 수 있는 양은 소량의 데이터를 저장할 수 있는 용도이기 때문에 대량의 정보를 저장하고 이를 다시 복구하기에는 한계가 있었습니다. 

 

이런 다양한 이유로 별도의 라이프사이클에 따라서 UI를 조금 더 편리하게 사용하기 위해서 viewModel이 등장하게 되었습니다.

 

- viewModel LifeCycle

 

뷰모델의 라이프사이클을 보면 액티비티의 라이프 사이클보다 훨씬 간단한 방법으로 오랫동안 유지가 됩니다. 또한 액티비티를 위한 뷰모델일 때, 액티비티가 파기되면서 같이 파기되므로 관리가 매우 쉬워진 것을 확인할 수 있습니다. 또한 별도의 클래스를 만들고 관리하기 때문에 대량의 데이터 저장이 가능해졌습니다.

 

이처럼 뷰모델은 라이프사이클이 존재하는 액티비티나 플래그먼트를 위해서 만들어집니다. 따라서 플래그먼트를 위해 만들어진 뷰모델이라면 플래그먼트가 파기 될 때 같이 파기 될 것이고 액티비티를 위한 뷰모델이라면 액티비티가 파기 될 때 같이 파기 될 것입니다. 

 

2. 특징


1) viewModel을 객체화는 new가 아닌 ViewModelProvider를 통해서 객체화 해야합니다.

- viewModel은 객체화를 ViewModelProvider를 통해서 하게 됩니다. 따라서 viewModel의 생성자로 여러 인자를 받더라도 아무 인자가 없는 기본 생성자를 통해서 만들어집니다. 하지만 그렇다고 해서 인자 값을 받는 방법이 없는 것은 아닙니다. 왜냐하면 ViewModel class 내에서 viewModel 생성을 위한 Factory를 만들면 되게 되면 인자 값을 갖는 viewModel을 생성할 수 있습니다.

 

2)viewModel은 hashMap으로 관리됩니다.

- viewModelProvider()의 인자는 ViewModelStoreOwner 하나입니다. 이때 viewModelStoreOwner interface가 getViewModelStore() 메서드를 통해서 viewModel을 hashMap으로 관리합니다. 따라서 라이프사이클이 존재하는 액티비티나 플래그먼트에 따라서 개별적으로 생성되고 만약 이미 존재하는 viewModel이 있다면 그 viewModel을 return 시켜서 객체화가 진행되도록 합니다. 

 

-viewModelStoreOwner

-viewModelStore

3. viewModel 생성


액티비티에서 버튼을 통해 숫자를 카운트하면 이를 Fragment에서 감지하고 값 셋팅하는 예를 통해서 viewModel을 사용해보도록 하겠습니다. 

 

먼저 viewModel을 만들기 위해서 ViewModel을 상속 받습니다. 추가적으로 필드로 사용되고 있는 MutableLiveData는 LiveData를 상속받아서 값을 set할 수 있도록 class입니다. 이런 LiveData를 사용하는 이유는 값이 변경되는 것을 Observer를 통해서 알 수 있게 되기 때문에 즉각적인 UI 변경을 처리할 수 있습니다. 

 

4. main.xml 구성


액티비티에서 주는 변화를 플래그먼트에서 감지하도록 만들기 위해서 main.xml에 button과 fragment가 생성될 공간인 frameLayout을 생성해 주도록합니다.

 

5. MainActivity에서 viewModel 객체화 


메인액티비티에서 ViewModelProvider를 통해서 viewModel을 객체화시켜주고 있습니다. this를 통해서 생성되기 때문에 HashMap에 현재 액티비티로 만들어 진 viewModel이 있는지 확인하고 없으면 새롭게 viewModel을 생성하여 return합니다. 

6. Fragment.xml 구성


메인 액티비티가 button을 클릭할 때마다 viewModel의 value값이 달라집니다. 이를 fragment에서 인지하여 화면 상에 표현 해 줄 것이기 때문에 간단하게 TextView하나만 생성해 줍니다.

 

7. Fragment에서 MainActivity의 viewModel 가져오기 


viewModelStoreOwner가 viewModel을 hashMap으로 관리한다고 했습니다. 따라서 fragment에서의 viewModelProvider는 requireActivity를 통해 자신이 속해있는 액티비티의 정보 값을 가져와서 viewModel을 리턴 받게 됩니다. (참고로 requireActivity는 getActivity()가 null일 때 error를 던져주는 메서드입니다.) 따라서 액티비티가 파기 되기 전까지 viewModel에서 관리되는 값은 절대 사라지지 않으며, 이 객체를 얻게 되면 객체의 인스턴스 변수 값들을 사용할 수 있게 됩니다.

 

추가적으로 LifeCycleOwner는 라이프 사이클을 갖고있는 액티비티와 플래그먼트에서 직접 구현하고 있기 때문에 플래그먼트에서 getViewLifeCyclerOwner() 메서드는 플래그먼트를 의미합니다. 즉 플래그먼트가 자신의 생명주기 동안 관찰을 이어나가겠다~ 뭐 이런 의미가 됩니다. 

 

8. 결과


'android' 카테고리의 다른 글

android ConstrainLayout  (2) 2020.08.24
room과 Rxjava2 같이 사용하기  (7) 2020.08.21
Retrofit2 사용해보기  (12) 2020.08.19
DataBinding 사용해보기  (2) 2020.08.17
Filterable로 자동검색 만들기  (0) 2020.08.17