2013년 10월 21일 월요일

FragmentPagerAdapter, FragmentStatePagerAdapter 차이

이전 블로그에서 이전 함 (원본 글 2013/10/21 작성)

한 Activity에서 Navigation Drawer의 메뉴에 따라서 Fragment들을 업데이트 해줘야할 필요가 있어
FragmentPagerAdapter 를 사용해서 구현하던 중 Fragment가 제대로 업데이트 되지 않는 현상 발생..

아무래도 FragmentPagerAdapter를 잘못 상속 구현한 것으로 보여 여기저기 찾아봄.
(참고했던 Android tab swipe sample code가 FragmentPagerAdapter + ViewPager를 사용하고 있어 이것을 그대로 사용했었음.)

결론적으로 fragment를 바로 destroy하지 않고 재사용하는 FragmentPagerAdapter 대신 FragmentStatePagerAdapter를 사용하고 getItemPosition()을 override하여 제거된 Fragment에 대해서 POSITION_NONE를 리턴하게 하여 구현 함.

관련 설명 및 링크는 다음과 같다.

[API documentation for FragmentPagerAdapter and FragmentStatePagerAdapter]

: Fragment manager에서 등록된 Fragment들을 최대한 영구적으로 가지고 있도록 구현되어 있고
소규모의 static한 fragment들을 사용할 경우에 추천되는 adapter.
* view가 invisible한 상황에서 destroyed되더라도 fragment들은 영구적으로 남아 있어 메모리를 차지함.
public abstract class

FragmentPagerAdapter

extends PagerAdapter 
   ↳

   ↳
android.support.v4.app.FragmentPagerAdapter

Class Overview


Implementation of PagerAdapter that represents each page as a Fragment that is persistently kept in the fragment manager as long as the user can return to the page.
This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs. The fragment of each page the user visits will be kept in memory, though its view hierarchy may be destroyed when not visible. This can result in using a significant amount of memory since fragment instances can hold on to an arbitrary amount of state. For larger sets of pages, consider FragmentStatePagerAdapter.
When using FragmentPagerAdapter the host ViewPager must have a valid ID set.
Subclasses only need to implement getItem(int) and getCount() to have a working adapter.



: FragmentPagerAdapter 에 비해 다소 많은 Fragment들을 관리해야 할 경우 추천되는 Adapter. listview와 유사한 behavior를 가지고 등록된 Fragment들이 이상 보이지 않을 경우 saved state 만을 보관하고 destroyed 함.
* Fragment들을 동적으로 create/destory 하므로 page switch시 overhead 발생.
public abstract class

FragmentStatePagerAdapter

extends PagerAdapter 
   ↳

   ↳
android.support.v4.app.FragmentStatePagerAdapter

Class Overview


Implementation of PagerAdapter that uses a Fragment to manage each page. This class also handles saving and restoring of fragment's state.
This version of the pager is more useful when there are a large number of pages, working more like a list view. When pages are not visible to the user, their entire fragment may be destroyed, only keeping the saved state of that fragment. This allows the pager to hold on to much less memory associated with each visited page as compared to FragmentPagerAdapter at the cost of potentially more overhead when switching between pages.
When using FragmentPagerAdapter the host ViewPager must have a valid ID set.
Subclasses only need to implement getItem(int) and getCount() to have a working adapter.


[기타 관련 링크]

like miller님의 "ViewPager를 사용해 보자2"

- 비교 및 FragmentPagerAdapter 예제, FragmentStatePagerAdpater 예제


  • Android FragmentStatePagerAdapter
  • Android FragmentPagerAdapter
  • Android FragmentPagerAdapter vs FragmentStatePagerAdapter




  • - 이건 좀 다른 얘기 일 수도 있지만 그래도 알아두면 유용할듯

    : 질문자는 Fragment 들이 업데이트 안되는 현상을 getItemPosition(Object object) 를 override하여 POSITION_NONE 를 항상 하여 무조건 fragment들을 재생성하여 업데이트 되도록 하였으나
    밑에 답변에서 해당 상황에서는 FragmentPagerAdpater, FragmentStatePagerAdapter를 상속할 경우 getItem()만을 override하고 그 외 API는 건들지 말라는 지적과 Fragment들의 업데이트?를 위해서는 FragmentStatePagerAdapter를 사용하라는 답변..

    Google API documentation에서 보듯이 위 Adapter들을 사용할 경우 두 API들( getItem(), getCount() )을 override 하는 것이 맞겠고 사용하는 Fragment들의 사용주기와 갯수에 따라서 Adapter들을 고르는게 맞을 것 같음.
    그리고 참고로 override한 getItemPosition()에서 argument(object)에 대해서 POSITION_NONE을 리턴할 경우 해당 object는 삭제가 되어야 하지만 이것은 FragmentStatePagerAdapter에서만 가능할 것 같음.

    댓글 1개:

    1. 이유가 궁금했는데 읽어보면서 대충 정리가 되네요
      save 가 필요할땐 pageAdapter 쓰고
      갱신이 필요하면 pageStateAdapter 쓰면 되겠네요

      답글삭제