seoft

프래그먼트 replace시 뷰 상태저장과 불러오기 시점 (with 프래그먼트 viewLifecycleOwner 생성시점) 본문

android

프래그먼트 replace시 뷰 상태저장과 불러오기 시점 (with 프래그먼트 viewLifecycleOwner 생성시점)

seoft 2020. 11. 22. 21:17

A프래그먼트의 onCreateView에 인플레이트된 뷰는 RecyclerView와 EditText를 가지고 있다

A프래그먼트를 B프래그먼트로 replace, commit 하고 다시 B프래그먼트에서 A프래그먼트로 replace, commit 하게 될 경우 기존의 RecyclerView 아이템들과 스크롤 포지션, 작성중인 EditText가 유지되는걸 확인할 수 있다.

그러면 어느시점에 어디에 저장되고 어느시점에 복구되는걸까?

 

 

 

복구되는 시점을 먼저 서술하면,

 

Fragment는 SparseArray<Parcelable>타입의 mSavedViewState를 가지고있고 이곳에 뷰의 상태를 저장시킨다

프래그먼트만을 확인했을때 onCreateView 콜백 호출 시점에는 mSavedViewState 를 보유중이며 onViewStateRestored 콜백 호출 시점에는 mSavedViewState가 null로 바껴버리는데, 이 두 콜백 사이에 사용되고 null로 전환된다

 

더 딥하게 추적 해봤을때 FragmentManager에서 moveToState라는 함수가있는데

void moveToState(@NonNull Fragment f, int newState)

교체되는 프래그먼트들의 생명주기와 생명주기 관련된 콜백을 호출하는 부분이다. 실제로 mState 라는 변수를 다음 const로 업데이트하며 관리한다

static final int INITIALIZING = -1; // Not yet attached.
static final int ATTACHED = 0; // Attached to the host.
static final int CREATED = 1; // Created.
static final int ACTIVITY_CREATED = 2; // Fully created, not started.
static final int STARTED = 3; // Created and started, not resumed.
static final int RESUMED = 4; // Created started and resumed.

moveToState 함수 내에서 ATTACHED 이후의 CREATED 되는 단계의 첫 함수에서 타고 타다가 performCreateView함수에서 FragmentViewLifecycleOwner 가 생성 되며,

동일한 함수스택에서 viewLifecycleOwner 생성 직후에 onCreateView 콜백을 호출하고 우리는 이 함수를 override받아 view객체를 inflate하여 넘겨준다

 

현시점에서 viewLifecycleOwner가 생성되고 프래그먼트에 나타 날 View도 인플레이트 된 시점이다

 

이어서 moveToState 내에서 activityCreated 호출을 통해 onActivityCreated override 함수가 콜백으로 호출되며
그다음 restoreViewState 가 호출되면서 프래그먼트가 가지고 있던 mSavedFragmentState를 인플레이트한 View에 복구하는 과정을 진행한다

 

그 직후에 onViewStateRestored override 함수가 콜백으로 호출되어 우리가 구현한 프래그먼트의 onViewStateRestored 콜백을 받는 시점에는 mSavedFragmentState가 null로 나오게 된다

 

그리고 이 시점에 viewLifecycleOwner의 내부를 ON_CREATE로 업데이트한다

 

 

 

다음은 저장하는 시점인데, 

 

프래그먼트만을 확인했을때 onStop 이후, onDestroyView 이전에 mSavedViewState가 저장된다

아까와 동일하게 moveToState 함수 내에서 새로 뛰어질 프래그먼트의 ACTIVITY_CREATED 과정에서 이전 프래그먼트의 mSavedViewState를 채워놓게되고 나중에 이를 사용하는 방식이다

 

 

 

요약한걸 이미지로 설명하면 다음과 같다

Comments