들어가기 전
이번 포스팅에서는 ViewModel의 LiveData를 View에서 observe 할 때 사용하는 LifecycleOwner를 잘못 사용한 나의 사례를 바탕으로 LifecycleOwner란 무엇인지, viewLifecycleOwner와 비교해 fragment에서는 무엇을 사용해야하는지에 대해 알아보고자 한다.
안드로이드 프로젝트에서 mvvm 패턴을 구현할 때, model 에서 받아온 데이터를 가공해 view에 제공하기 위해서 viewModel을 활용한다. 이 때 AAC ViewModel에서 LiveData를 활용해 observerPattern을 이용할 것이다. 아래는 예시 코드이다.
[그림 1]은 ViewModel에서 listQnaResponse라는 LiveData 객체를 생성하고, View에서는 LiveData 객체의 데이터가 변경될 때 발생하는 작업을 제어하는 Observer 객체를 만든다. 그리고 observe() 메서드를 사용해 LiveData 객체에게 Observer를 붙인다. 이 때 observe() 메서드는 LifecycleOwner 객체를 가지는데, 위 코드에서 observe(owner) 에 해당하는 부분이다. 그렇다면 LifecycleOwner란 무엇일까?
LifecycleOwner란?
LifecycleOwner는 클래스에 Lifecycle이 있음을 나타내는 단일 메서드 인터페이스 이다.
이 인터페이스에는 클래스에서 구현해야하는 getLifecycle() 메서드가 하나 있다.
즉 안드로이드 생명주기를 알고 있는 클래스라 생각하면 된다. activity나 fragment에서 이를 상속하고 있다.
관찰자가 관찰을 위해 등록할 수 있는 수명주기를 소유자가 제공할 수 있으므로
따라서 observe 메서드 LifecycleOwner 매개변수로 activity나 fragment를 넣으면 이들의 생명주기에 따라 LiveData를 처리하겠다는 뜻이다. 만약 activity의 경우 onCreate() ~ onDestroy() 까지, fragment의 경우 onAttach() ~ onDestroy() 에 따라 처리한다고 생각하면 된다.
나는 이 부분을 모르고 Activity에서는 observe lifecycleOwner를 this로 설정했지만, fragment에서 마저 requireActivity()로 설정을 했다. (전부 activity의 생명주기로 observe lifecycleOwner를 설정한 것이다.) 아래와 같이 말이다.
이렇게 설정하면 무엇이 문제일까? 이는 메모리 누수를 발생시킨다 !!
Fragment 에서 lifecycleOwner
lifecycleOwner는 위 설명과 같이 프래그먼트 자체의 생명주기를 갖는다. 따라서 onAttach() ~ onDestroy() 와 연관되어있다. 프래그먼트는 액티비티와 다르게 onDestory가 호출되지 않은 상태에서 onCreateView가 여러번 호출될 수 있다.
예시로 home, list, setting 프래그먼트가 있다고 할 때 home 프래그먼트에서 bottom navigation을 이용해 list 프래그먼트로 이동하게 된다면, home 프래그먼트의 onDestroyView()가 호출되어 프래그먼트의 뷰는 소멸되지만, onDestroy()는 호출되지 않아 프래그먼트 자체는 여전히 남아있게된다.
이렇게 되면 list 프래그먼트로 이동했다고 해도, home 프래그먼트에서 사용했던 LiveData는 그대로 남아있게되고, 이는 메모리 누수를 발생시키는 것이다.
viewLifecycleOwner란?
따라서 프래그먼트가 destory 되지 않은 상태에서 LiveData에 새로운 observer가 등록되어 여러개의 Observer가 호출되는 현상이 발생할 수 있는 것이다. 이러한 현상을 해결하기위해서 등장한게 viewLifecycleOwner이다.
viewLifecycleOwner는 onCreateView() ~ onDestroyView() 까지의 생명주기를 갖는다. 따라서 onDestroyView()에서 DESTROYED 된다는 점에서 위 문제를 해결할 수 있다.
[그림 4]와 같이 fragment에서 LiveData를 올바르게 사용하기 위해서는 viewLifecycleOwner를 사용하면 된다.
이렇게 사용한다면 프래그먼트가 replace 되어도 onDestroyView에서 view lifecycle이 폐기되기 때문에 중복으로 Observe하는 가능성을 없애준다.
마치며
view에서 LiveData를 observe 할 때, activity에서는 this를 사용하길래 fragment에서는 requireActivity()를 사용해야지~ 하며 아무 생각없이 사용을 했었다. 이번 공부를 통해서 activity에서는 왜 owner에 this를 넣는지, fragment에서는 this를 왜 사용하면 안되는지를 알 수 있었다. 메모리 누수와 같은 문제도 생각하는 디테일한 코드를 작성하기 위해 노력해야겠다.
참고 레퍼런스
Fragment LiveData와 viewLifecyclewOwner
안드로이드 개발(28) ViewLifeCycleOwner
https://developer.android.com/topic/libraries/architecture/lifecycle?hl=ko
'Android > 공부' 카테고리의 다른 글
[Android/코루틴] 1. 코루틴은 무엇이고 왜 쓰는가? (0) | 2023.09.21 |
---|---|
[Android] 첫 안드로이드 앱 릴리즈 과정에서 겪은 트러블슈팅들 (0) | 2023.09.11 |
[Android] UI State란 무엇일까? (0) | 2023.08.16 |
[Android] Dependency Injection이란? + Hilt (1) | 2023.08.07 |
[Android] Clean Architecture + MVVM 패턴 (1) | 2023.08.06 |