본문 바로가기

Programming/Android_Kotlin

lifecycleOwner와 viewLifecycleOwner의 차이

Fragment에서 LiveData를 observe할 때 LifecycleOwner로 Fragment 자체를 넣게 되면 viewLifecycleOwner를 사용하라는 에러가 표시된다.

처음엔 Fragment는 lifecycleOwner가 따로 없어서 viewLifecycleOwner를 사용해야하는구나 하고 넘어갔다.

당연한 건 없었다….

Fragment는 분명 LifecycleOwner를 상속받고 있기 때문에 LiveData의 observe에서도 사용이 가능한 게 정상이다.

심지어 DataBinding의 lifecycleOwner에는 정상적으로 잘 들어가지만 observe에서 사용할 때만 빨간줄로 에러가 표시된다.


그 이유는 Fragment의 lifecycleOwner와 viewLifecycleOwner가 관장하고있는 생명주기가 다르기 때문에 Lint에서 올바르게 사용하도록 경고하는 것이다. (실제로 빨간 줄이 떠있음에도 정상적으로 빌드가 된다.)

기본적으로 Activity와 Fragment의 생명주기는 아래 그림과 같다.

출처 : The Android Lifecycle cheat sheet — part III : Fragments

여기서 중요한 부분은 Fragment의 경우 자체의 생명주기와 프래그먼트 뷰의 생명주기가 별도로 존재한다는 점이다. lifecycleOwner와 viewLifecycleOwner의 차이도 여기서 발생하는데 정리하자면 아래와 같다.

lifecycleOwner

Fragment 자체의 생명주기와 연동

  • onAttach() ~ onDestroy()

viewLifecycleOwner

Fragment View의 생명주기와 연동

  • onCreateView() ~ onDestroyView()

그렇다면 왜 LiveData를 observe할 때 lifecycleOwner를 사용하지 않도록 하는 걸까? 답은 onDestroy()가 호출되기 전에 onCreateView()가 여러번 호출될 수 있기 때문이다.

가령 내비게이션을 활용해서 페이지를 이동할 때도 onDestory()는 호출되지 않고 onDestroyView()만 호출된다.

이렇게 되면 어떤 문제가 있는가 하니… 우선 보통 Fragment에서 onCreateView()에 observe 로직을 구현하는데 lifecycleOwner를 사용할 경우 다른 페이지에 갔다 다시 돌아왔을 때 프로그먼트 자체는 아직 살아있기 때문에 LiveData를 계속 observe하고 있는 상태이다. 여기서 onCreateView()는 다시 실행되므로 observe를 한 번 더 해서 Observer가 중복으로 달리는 문제가 발생한다.

또 페이지를 다시 돌아오지 않는다 하더라도 사용하지 않는 LiveData가 그대로 남게 되기 때문에 메모리 누수를 초래할 수 있다.

따라서 일반적인 경우에는 Fragment에서 LiveData를 Observe할 땐 viewLifecycleOwner 사용이 권장된다.


참고

http://pluu.github.io/blog/android/2020/01/25/android-fragment-lifecycle/

https://velog.io/@jeongminji4490/Android-LifecycleOwner-vs-viewLifecycleOwner-in-Fragment