[Android] Fragment ViewLifecycleOwner

ViewLifecycleOwner?

Posted by 동식이 블로그 on July 28, 2022

[Android] Fragment ViewLifecycleOwner

[Android] Fragment Lifecycle 글에 이에서 Fragment에서 사용하는 ViewLifecycleOwner에 관한 내용이다

Fragment에는 두 가지 Lifecycle이 존재한다 (Fragment Lifecycle, Fragment View Lifecycle).

이 전 글이 두 가지의 Lifecycle에 관한 내용이라면, 이번 글은 viewLifecycleOwner에 대한 내용이다.

Lifecycle이 달라서 viewLifecycleOwner를 쓰면 된다고 했는데, 얘는 과연 어떻게 생성되고 null처리가 되는지 알아보자

ViewLifecycleOwner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// androidx.fragment.app.Fragment.java

void performCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
    mChildFragmentManager.noteStateNotSaved();
    mPerformedCreateView = true;
    mViewLifecycleOwner = new FragmentViewLifecycleOwner(this, getViewModelStore()); // #1
    mView = onCreateView(inflater, container, savedInstanceState); // #2
    if (mView != null) {
        // Initialize the view lifecycle
        mViewLifecycleOwner.initialize();
        // Tell the fragment's new view about it before we tell anyone listening
        // to mViewLifecycleOwnerLiveData and before onViewCreated, so that calls to
        // ViewTree get() methods return something meaningful
        ViewTreeLifecycleOwner.set(mView, mViewLifecycleOwner);
        ViewTreeViewModelStoreOwner.set(mView, mViewLifecycleOwner);
        ViewTreeSavedStateRegistryOwner.set(mView, mViewLifecycleOwner);
        // Then inform any Observers of the new LifecycleOwner
        mViewLifecycleOwnerLiveData.setValue(mViewLifecycleOwner);
    } else {
        if (mViewLifecycleOwner.isInitialized()) {
            throw new IllegalStateException("Called getViewLifecycleOwner() but "
                    + "onCreateView() returned null");
        }
        mViewLifecycleOwner = null;
    }
}

Fragment.java에 들어가보면 performCreateView에서 #2 onCreateView 호출 이전에 #1 FragmentViewLifeCycleOwner가 생성되는 걸 볼 수 있는데, 따라서 onCreateView 이전에 viewLifecycleOwner를 사용해도 된다고 볼 수 있다.

1
2
3
// This is initialized in performCreateView and unavailable outside of the
// onCreateView/onDestroyView lifecycle
@Nullable FragmentViewLifecycleOwner mViewLifecycleOwner;

실제로 mViewLifecycleOwner가 선언된 곳을 가보면 이렇게 주석이 달려있다. (performCreateView에서 초기화되며 onCreateView/onDestroyView 라이프사이클 이외에서는 사용할 수 없다)

그렇다면 이 nullable한 viewLifecycleOwner는 언제 null로 바뀌는지 알아보자

mViewLifecycleOwner를 쫓아가보면

1
2
3
4
5
6
7
8
9
10
11
12
13
// androidx.fragment.app.FragmentManager.java

private void destroyFragmentView(@NonNull Fragment fragment) {
    fragment.performDestroyView(); // #1
    mLifecycleCallbacksDispatcher.dispatchOnFragmentViewDestroyed(fragment, false);
    fragment.mContainer = null;
    fragment.mView = null;
    // Set here to ensure that Observers are called after
    // the Fragment's view is set to null
    fragment.mViewLifecycleOwner = null; // #2
    fragment.mViewLifecycleOwnerLiveData.setValue(null);
    fragment.mInLayout = false;
}

#2 에서 null 처리를 해주고있다. 하지만 그 전 #1 , performDestoryView가 호출되는데

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// androidx.fragment.app.Fragment.java

void performDestroyView() {
    mChildFragmentManager.dispatchDestroyView();
    if (mView != null && mViewLifecycleOwner.getLifecycle().getCurrentState()
                    .isAtLeast(Lifecycle.State.CREATED)) {
        mViewLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
    }
    mState = CREATED;
    mCalled = false;
    onDestroyView(); // #1
    if (!mCalled) {
        throw new SuperNotCalledException("Fragment " + this
                + " did not call through to super.onDestroyView()");
    }
    // Handles the detach/reattach case where the view hierarchy
    // is destroyed and recreated and an additional call to
    // onLoadFinished may be needed to ensure the new view
    // hierarchy is populated from data from the Loaders
    LoaderManager.getInstance(this).markForRedelivery();
    mPerformedCreateView = false;
}

여기에서 #1 , 즉 onDestoryView()가 호출된다

정리해보면, onDestroyView가 호출되고 그 이후에 mViewLifecycleOnwer가 null로 변하게 된다

ViewLifecycleOwnerLiveData

mViewLifecycleOnwer를 따라가다 보면 mViewLifecycleOnwer값을 변경해주면서 mViewLifecycleOwnerLiveData값까지 같이 변경시켜주는 부분을 볼 수 있다

1
MutableLiveData<LifecycleOwner> mViewLifecycleOwnerLiveData = new MutableLiveData<>();

mViewLifecycleOwnerLiveData를 이용하면 Fragment View 생성과정을 떠나 순수하게 ViewLifecycleOwner만 바라보고 작업을 할 수도 있다

1
2
3
4
5
6
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    viewLifecycleOwnerLiveData.observe(this) {
				...
		}
}

참고사이트