Android ViewPager2 간단히 뜯어보기
BABA 라는 Android Application side project 을 하는 도중 아래와 같은 화면을 만들어야 했습니다.
이 때 ViewPager2 에 대한 이해가 부족한 것 같아 공부하게 되었습니다.
(물론 아래 gif 는 ViewPager2 와 Custom 한 TabLayout 을 같이 사용한 것입니다.
viewPager2 의 내부 동작 방식
ViewPager2
는 FragmentStateAdapter
을 extend 해서 구현해야 합니다.
그런데 FragmentStateAdapter
는 RecyclerView.Adapter<FragmentViewHolder>
을 extend 하고 있습니다.
즉, ViewPager2 는 RecyclerView.Adapter
을 사용하여 동작합니다.
RecyclerView
에서의 Item 은 List 의 각 항목임에 반해서 ViewPager2
에서의 Item 은 각 페이지인 것입니다. (예를 들어 Fragment).
FragmentStateAdapter
FragmentStateAdapter
는 ViewPager2
가 제공하는 어댑터 클래스로 각 페이지를 Fragment
로 구성하고 싶을 때 사용할 수 있습니다
RecyclerView.Adapter 는 RecyclerView.Adapter 인데 이 때 타입을 FragmentViewHolder 로 고정하고 있습니다.
그리고 StatefulAdapter 라는 인터페이스도 구현하고 있습니다.
FragmentStateAdapter
는 getItemCount()
와 createFragment()
을 오버라이드 해야 합니다.
getItemCount()
:RecyclerView.Adapter
의 abstract function
위에서 말했듯이 여기서 Item 은 Fragment 가 됩니다.
createFragment()
:FragmentStateAdapter
의 abstract function
설명은 이렇습니다.
Provide a new Fragment associated with the specified position
The adapter will be responsible for the Fragment lifecycle.
- The Fragment will be used to display an item.
- The Fragment will be destroyed when it gets too far from the viewport, and its state will be saved. When the item is close to the viewport again, a new Fragment will be requested, and a previously saved state will be used to initialized it.
- viewport 로부터 멀리 떨어지면 fragment 가 destroy 되고 상태가 저장되며, 다시 viewport 로부터 가까워지면 저장된 상태로 다시 초기화된다는 것이 멋있네요.. 이것이 동작하는 것을 자세히 뜯어보면 많은 도움이 될 것 같습니다.
FragmentStateAdapter 생성자
parameter 가 다른 세가지 생성자 함수가 있습니다.
세 번째, 두 번째, 첫 번째 순서로 봅시다.
세 번째 FragmentManager 와 lifecycle 이 인수로 있는 함수
FragmentStateAdapter
클래스에서 fragment 을 관리하기 위해 FragmentManager
가 필요합니다.
Lifecycle 은 FragmentStateAdapter
클래스 내부에서 lifecycle observer 을 달아서 특정 lifecycle 지점에서 그에 맞는 작업을 하기 위해 전달받는 것으로 보입니다.
이 생성자 함수는 첫번째, 두번째 함수에서 this
입니다. 1,2 번째 함수를 보면 function body 안에 fragmentManager
와 해당 view 의 lifecycle
을 받는 것을 알 수 있습니다.
첫 번째 FragmentActivity 가 인수로 있는 함수
fragment 가 붙은 activity 인스턴스를 인수로 받습니다.
내부적으로는 세번째 생성자 함수를 호출하고 있으며 이 때 액티비티의 supportFragmentManager
와 Activity 의 lifecycle
을 넘기고 있습니다.
ViewPager2 를 Activity에 배치할 때 이 생성자 함수를 사용하면 될 것입니다.
두 번째 Fragment 가 인수로 있는 함수
fragment 인스턴스를 전달받습니다. 내부적으로는 세 번째 생성자 함수를 호출하고 이 때, fragment 의 childFragmentManager
와 fragment 의 lifecycle
을 넘기고 있습니다.
ViewPager2 을 Fragment 에 배치할 때 이 생성자 함수를 사용하면 될 것입니다.
ViewPager2 을 Fragment 에 붙이면서 각 페이지를 또 다른 fragment 로 구성하는 경우입니다.
StatefulAdapter
그렇다면 FragmentStateAdapter
가 구현하고 있는 StatefulAdapter
는 무엇일까요?
FragmentStateAdapter
는 아래 interface 을 implement 하고 있습니다.
파라미터로 Parcelable
객체를 가지고 있고 restoreState()
라는 함수를 정의하고 있습니다.
주석 설명: ViewPager2 adapter
는 View.onSaveInstanceState
() 와 View.onRestoreInstanceState(Parcelable)
동안에 호출할 이 인터페이스를 implement 해야 합니다.
실제로 ViewPage2.java
클래스에서 adapter 가 StatefulAdapter
을 구현하고 있으면 상태를 회복해야 하는 시점에 restoreState()
을 호출하고 잇는 부분이 있습니다.
실제로 StatefulAdapter
을 implement 하는 FragmentStateAdapter
에서 Fragment 을 가지는 Array 와 Fragment.SavedState 을 갖는 Array 가 있는 것을 확인할 수 있습니다. 아래처럼 말이죠..
정리
FragmentStateAdapter
는 각 페이지를 Fragment 로 구성하고 싶을 때 사용합니다.
내부적으로 모든 페이지의 fragment 인스턴스가 아닌 필요한 만큼의 인스턴스만 가지고 있고 나머지 페이지에 대해서는 상태값만 들고 있는 구조입니다.
Reference Link -
[안드로이드] ViewPager2의 FragmentStateAdapter 동작 원리
https://developer.android.com/guide/navigation/navigation-swipe-view-2?hl=ko