보통 view를 제어하는 것은 너무나도 번거롭고 많은 작업을 요구하기 때문에, 데이터를 일정하게 유지하거나 변경하는 것으로 viewmodel을 사용합니다. 무엇보다도 기존의 android가 가질수 있는 recomposition 의 발생시 onSaveInstanceState() 를 사용하게 된다면 recomposition 이 발생할때마다 메인스레드에서 같은 작업이 반복 실행 되어 앱이 제대로 작동하지 않게될 가능성이 있습니다. 오늘은 viewmodel 이 주는 간편함이 얼마나 좋은 것인지 알아보겠습니다.
viewmodel을 사용하기 전에 viewmodel을 사용하지 않고 데이터를 유지 하기 위해서 사용했던 것은 Actvitiy
의 oncreate 의 savedInstanceState
입니다. 이곳에 인스터스 데이터를 담아 유지할 수 있으며 bundle serialization 하는 소용량 데이터를 적용할 수 있습니다.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
final AppCompatDelegate delegate = getDelegate();
delegate.installViewFactory();
delegate.onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
getDelegate().onSaveInstanceState(outState);
}
savedInstanceState로 들어오게 되는 데이터들은 다음의 그림과 같이 re-composition이 생기면 onSavedInstanceState
를 override 해서 데이터를 유지하게 해줄수 있습니다.
해당 lifecycle로 데이터를 유지하기 때문에 onRestoreInstanceState를 사용하여 복원하는 경우도 있다고 합니다.
데이터가 단순한 경우는 onSaveInstanceState()
메서드를 사용하여 onCreate()
의 bundle에서 데이터를 복원할 수 있습니다. 하지만 이 접근 방법은 직렬화했다가 다시 역직렬화할 수 있는 소량의 데이터에만 적합하며 사용자 목록이나 비트맵과 같은 대용량일 가능성이 높은 데이터에는 적합하지 않습니다.
그리고 가장 큰 문제점으로는 UI 를 적용하는데 메인스레드를 사용하여 비동기 호출을 하게 될때 구성이 변경되게 되면 재 호출시에 리소스의 낭비가 증가하기 때문입니다.
viewmodel은 fragment 또는 activity와 다른 생명주기를 갖습니다. 보통은 fragment와 activity 보다 길게 데이터를 유지하고 있기 때문에 activity 내에서 recomposition 이 일어나더라도 NonConfigurationInstances 객체를 유지하고 있기 때문에 가능한것입니다.
일반적으로 activity 생성시에 viewmodel을 사용할 수 있게 기본으로 implement를 해주는 부분이 있는데요. 바로 ViewModelStoreOwner
입니다. 이 인터페이스에서는 viewmodel이 가지는 데이터들을 가져올 수 있게 정의하고 있습니다.
package androidx.lifecycle;
import androidx.annotation.NonNull;
@SuppressWarnings("WeakerAccess")
public interface ViewModelStoreOwner {
@NonNull
ViewModelStore getViewModelStore();
}
viemodel을 사용하기위해서 필요한 것이 하나더 있는데요. 인스턴스를 담기 위한 그릇에 해당하는 ViewModelProvider.Factory
입니다. 여기서 ViewModelProvider
의 constructor는 세가지가 존재 합니다
생성자 오버로딩 되어 가지 형태로 상황에 맞게 사용하고 있습니다
결론적으로 ViewModelStoreOwner에서 생성한 ViewModelStore에서 key-value 쌍의 viewModel을 관리하고 있습니다.
하지만 viewmodel 은 시스템에 의해 프로세스가 중단 될 경우에는 onSaveInstanceState()
를 사용해야 할 수 있는데요. 하지만 이렇게 하면 유지 보수가 까다롭기 때문에 SavedState ViewModel 라이브러리를 제공해주고 있다고 하네요.
implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'
해당 라이브러리를 사용하는 방법은 기존의 viewmodel 사용법과 조금은 차이가 있기 때문에 따로 포스팅 할 것입니다
viewmodel에서 데이터를 저장하는 이유는 lifecycle이 fragment, actvity와 다르기 때문에 recomposition시에도 데이터를 유지할 수 있기 때문입니다. 또 가장 좋은 것은 UI와 관련된 데이터들을 activity나 fragment에서 관리 하지 않게 할수 있게 됨으로서 유지보수적으로도 더 좋다고 생각이 듭니다.