[MVVM 정복] 2. SnackbarMessage, BaseViewModel, BaseActivity
코드는 내 깃헙을 참고하면 된다. 커밋 로그와 블로그 포스팅 제목이 유사하게 따라간다.
SnackbarMessage
SnackbarMessage는 SingleLiveEvent이다. 앞 포스팅에 있는 그 SingleLiveEvent이다.
Snackbar에 보여주고 싶은 메세지가 있다면 이 이벤트의 value에 원하는 메시지를 담으면 된다.
class SnackbarMessage : SingleLiveEvent<Int>() {
fun observe(owner: LifecycleOwner, observer: (Int) -> Unit) {
super.observe(owner, Observer {
it?.run {
observer(it)
}
})
}
}
위의 super.observe는 SingleLiveEvent에 있는 override fun observe이며 SnackbarMessage의 value가 변경되면 observer(it)이 수행된다. 여기서 람다식이 많이 나오는데 다른 블로그에서 설명을 잘 해두었다. 참고하길 바란다. 또한 LifecycleOwner라는 것이 등장하는데 그건 여기서 확인해보도록 하자.
LifecycleOwner
public interface LifecycleOwner {
/**
* Returns the Lifecycle of the provider.
*
* @return The lifecycle of the provider.
*/
@NonNull
Lifecycle getLifecycle();
}
단일 메소드를 가지는 이 인터페이스는 AppCompatActivity 내부에 존재하고 있다. 그 외에도 많은 뷰에 포함되어 있다. 이 인터페이스는 해당 뷰가 어떤 라이프사이클에 도달해 있는지 알 수 있다. 이 경우에는 Observer가 라이프사이클을 확인할 수 있어서 적절한 타이밍에 초기화 혹은 Cleanup을 진행할 수 있다.
BaseViewModel
우리가 알아야하는 ViewModel은 두가지이다.
- AAC의 ViewModel
- UI와 관련된 데이터를 저장/관리
- 스크린 회전을 할 때, View의 객체가 재생성되어서 데이터를 다시 갱신해야 하는데 이 변화에도 데이터가 잘 보존되도록 해준다.
- 액티비티 스코프의 싱글톤객체처럼 사용할 수 있다. 프래그먼트 사이에서 viewModel을 이용하여 데이터를 쉽게 공유할 수 있다.
- viewModel내부에 액티비티, 프레그먼트, 뷰에 대한 컨텍스트를 저장해서는 안된다.
- viewModel은 기기의 구성이 변경될때만 유지. 백버튼이나 , 최근목록에서 앱을 종료했을때는 어떠한 처리도 기대할 수 없다.
- MVVM의 ViewModel
- 비즈니스 로직이 들어가는 부분. 데이터를 가공해서 View에 보여지게 Model로 바꾸는 역할이다.
- ViewModel에서 직접 View에 데이터를 전달하지 않는다. Data binding을 통해 View가 갱신된다.
안드로이드에서 Data binding을 하는 방법은 세가지가 있다.
- 직접 Observer패턴을 이용한 Data binding을 구현
- 안드로이드에서 제공하는 ViewModel을 사용
- RxJava2를 사용하는 방법 (요즘 트렌드)
스낵바를 처리하는 로직이 왜 ViewModel에 있을까? 보통 특정 데이터가 어떤 조건에 부합할 때 토스트나 스낵바가 뜨기 마련이다. 그렇다면 해당 데이터는 obobserve되어 있어야 하기에 ViewModel에서 처리를 하는 것이다. observeSnackbarMessage를 사용하는 BaseActivity도 살펴보자.
BaseActivity
- lateinit var viewDataBinding: T
- 데이터바인딩으로 뷰(xml)를 갱신할 수 있도록 세팅
- abstract val layoutResourceId: Int
- setContentView로 호출할 Layout의 리소스 Id.
- ex) R.layout.activity_sbs_main
- abstract val viewModel: R
- viewModel 로 쓰일 변수.
- abstract fun initStartView()
- 레이아웃을 띄운 직후 호출.
- 뷰나 액티비티의 속성 등을 초기화.
- ex) 리사이클러뷰, 툴바, 드로어뷰..
- abstract fun initDataBinding()
- 두번째로 호출. 데이터 바인딩 및 rxjava 설정.
- ex) rxjava observe, databinding observe..
- abstract fun initAfterBinding()
- 바인딩 이후에 할 일을 여기에 구현.
- 그 외에 설정할 것이 있으면 이곳에서 설정.
- 클릭 리스너도 이곳에서 설정.
마지막으로, snackbarObserving이 있다. 앞에서 언급한 것처럼 ViewModel에서 라이프사이클 상의 뷰를 관측하기 위해 존재하며, 특정 이벤트가 발생했을 때 스낵바를 띄우기 위함이다.
참고자료
https://tourspace.tistory.com/24
https://www.bsidesoft.com/5999
https://developer.android.com/topic/libraries/architecture/lifecycle?hl=ko