Android/UI

Android ViewPager2 간단히 뜯어보기

sh1mj1 2023. 5. 5. 11:14

BABA 라는 Android Application side project 을 하는 도중 아래와 같은 화면을 만들어야 했습니다.

이 때 ViewPager2 에 대한 이해가 부족한 것 같아 공부하게 되었습니다.

(물론 아래 gif 는 ViewPager2 와 Custom 한 TabLayout 을 같이 사용한 것입니다.

 

 

 

viewPager2 의 내부 동작 방식

ViewPager2FragmentStateAdapter 을 extend 해서 구현해야 합니다.

 

 

그런데 FragmentStateAdapterRecyclerView.Adapter<FragmentViewHolder> 을 extend 하고 있습니다.

즉, ViewPager2 는 RecyclerView.Adapter 을 사용하여 동작합니다.

RecyclerView 에서의 Item 은 List 의 각 항목임에 반해서 ViewPager2 에서의 Item 은 각 페이지인 것입니다. (예를 들어 Fragment).

 

FragmentStateAdapter

FragmentStateAdapterViewPager2 가 제공하는 어댑터 클래스로 각 페이지를 Fragment 로 구성하고 싶을 때 사용할 수 있습니다

 

 

RecyclerView.Adapter 는 RecyclerView.Adapter 인데 이 때 타입을 FragmentViewHolder 로 고정하고 있습니다.

그리고 StatefulAdapter 라는 인터페이스도 구현하고 있습니다.

 

FragmentStateAdaptergetItemCount()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.

  1. The Fragment will be used to display an item.
  2. 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.
  3. 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 adapterView.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