뷰모델 개요
뷰모델 클래스는 수명주기를 고려하여 UI관련 데이터를 저장하고 관리하도록 설계되었습니다.
이 클래스를 이용하여 화면 회전과 같이 구성을 변경할 때도 데이터를 유지할 수 있습니다.
뷰 모델 클래스는 수명주기에 상관없이 데이터를 사용하기위해 사용한다.
안드로이드에서는 액티비티 및 프래그먼트와 같은 UI컨트롤러의 수명주기를 관리합니다.
프레임워크는 특정 사용자 작업이나 완전히 통제할 수 없는 기기 이벤트에 대한 응답으로 UI컨트롤러를 제거하거나 다시 만들도록 결정할 수 있습니다.
안드로이드는 상황에 따라 리프레시가 일어난다.
시스템에서 UI컨트롤러를 제거하거나 다시 만들면 컨트롤러에 저장된 일시적인 모든 UI 관련 데이터가 손실됩니다.
예를 들어 앱에 있는 액티비티 중 하나는 사용자 목록 데이터를 가지고 있을 수 있습니다.
Config 변경을 위해 액티비티를 다시 생성하면 새 활동은 사용자 목록을 다시 가져와야 합니다.
데이터가 단순한 경우 활동은 onSaveInstanceState() 메서드를 이용해 onCreate()번들에서 데이터를 복원할 수 있습니다.
하지만 이 접근 방법은 사용자 목록이나 비트맵과 같은 대용량 데이터가 아니라, 직렬화 후 역직렬화할 수 있는 소량의 데이터에만 적합합니다.
리프레시가 일어나 다시 실행되는 경우, UI관련 데이터가 사라진다. 이런 일이 일어나기에 뷰모델을 사용한다.
액티비티 및 프래그먼트와 같은 UI 컨트롤러는 주로 UI 데이터를 표시하거나, 사용자 작업에 반응하거나, 권한 요청과 같은 운영체제 커뮤니케이션을 처리하기 위한 것입니다. 또한 UI 컨트롤러에 데이터베이스나 네트워크에서 데이터 로드를 담당하도록 요구하면 클래스가 팽창됩니다. UI 컨트롤러에 과도한 책임을 할당하면 단일 클래스가 다른 클래스에 작업을 위임하지 않고 홀로 모든 앱 작업을 처리하려고 할 수 있습니다. 또한 이런 방법으로 UI 컨트롤러에 과도한 책임을 할당하면 테스트가 훨씬 더 어려워집니다.
액티비티나 프래그먼트는 사용자와의 인터페이스 역할을 하는데, 여기에 비즈니스 로직을 넣으면 관리가 어려워진다.
UI 컨트롤러 로직에서 뷰 데이터 소유권을 분리하는 방법이 훨씬 더 쉽고 효율적입니다.
데이터를 따로 관리하는 것이 더 쉽고 효율적이다.
뷰모델 구현
아키텍처 구성요소는 UI의 데이터 준비를 담당하는 UI 컨트롤러에 뷰모델 도우미 클래스를 제공합니다.
뷰모델 개체는 구성이 변경되는 동안 자동으로 보관되므로, 이러한 개체가 보유한 데이터는 다음 활동 또는 프래그먼트 인스턴스에서 즉시 사용할 수 있습니다. 예를 들어 앱에서 사용자 목록을 표시해야 한다면 다음 샘플 코드에서와 같이 사용자 목록을 확보하여 활동이나 프래그먼트 대신 뷰모델에 보관하도록 책임을 할당해야 합니다.
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<User>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
그 후 다음과 같이 액티비티에서 목록에 접근할 수 있습니다.
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
// 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.
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
액티바티가 다시 생성되면 첫 번째 액티비티에서 생성된 동일한 MyViewModel 인스턴스를 받습니다. 소유자 활동이 완료되면 프레임워크는 리소스를 정리할 수 있도록 뷰모델 개체의 onCleared() 메서드를 호출합니다.
*주의: 뷰모델은 뷰, 라이브사이클 또는 액티비티 컨텍스트에 대한 참조를 포함하는 클래스를 참조하면 안된다.
뷰모델 객체는 뷰 또는 LifecycleOwners의 인스턴스보다 오래 남아있도록 설계되었습니다. 이러한 설계로 뷰 및 라이프사이클 객체에 대해 알지 못해도 뷰모델을 다루는 테스트를 쉽게 작성할 수 있습니다.
뷰모델 객체에는 라이브데이터 객체같은 LifecycleObsers가 포함될 수 있습니다. 그러나 뷰모델 객체는 라이브데이트 객체같은 수명주기를 인식하는 Observable의 변경상항을 관찰해서는 안됩니다.
뷰모델은 시스템 서비스를 찾는 데 애플리케이션 컨텍스트가 필요하면 안드로이드 뷰모델 클래스를 확장하고 생성자에 애플리케이션을 받는 생성자를 포함할 수 있습니다.
뷰모델의 수명 주기
뷰모델 객체의 범위는 뷰모델을 가져올 때 뷰모델프로바이더에 전달되는 라이프사이클로 지정됩니다.
뷰모델은 범위가 지정된 라이프사이클이 영구적으로 경과될 때 까지, 즉 액티비티가 끝날때까지, 혹은 프래그먼트가 분리될 때까지 메모리에 남아있습니다.
뷰모델은 라이프사이클이라는 값으로 범위가 지정된다. 그리고 범위가 지정된 만큼 메모리에 남아있다.
일반적으로 시스템에서 액티비티 객체의 onCreate()메서드를 처음 호출할 때 뷰모델을 요청합니다.