본문 바로가기

안드로이드/오류해결

[안드로이드/Android] FragmentStatePagerAdapter 사용시 주의 사항

반응형

FragmentPagerAdapter

:프래그먼트 갯수가 정해졌을때 사용하면 좋습니다.

:엑티비티가 끝나기전까진 fragment 인스턴스가 사라지지 않습니다.

 

FragmentStatePagerAdapter

:프래그먼트 갯수가 일정치 않거나 많을 경우 사용하면 좋습니다.

:사용자가 보고 있지 않거나 범위 밖의 fragment는 없애고 다시 범위 안으로 들어왔을때 재생성 한다.  ( setOffscreenPageLimit 으로 정한 범위 )

- 어뎁터를 사용해서 정적인 개수의 프래그먼트를 뗏다 붙였따를 반복하면 'already add Item' 에러 발생 ( 20.07.09 ) : fragmentPagerAdapter로 변경

 

사용법

FragmentStatePagerAdapter나 FragmentPagerAdapter를 상속 받는 클레스를 만들어서 getItem 메소드를 이용해 포지션별 프래그먼트를 정의해줍니다.

 

class PagerAdapter extends FragmentStatePagerAdapter {

        private int pageCount;

        public PagerAdapter(FragmentManager fm) {
            super(fm);
        }


        @Override
        public Fragment getItem(int position) {


            switch (position) {
                case (INDEX_A): { 
                    if (aFragment == null)
                        aFragment = new AFragment();
                    return aFragment;
                }

                case (INDEX_B): { 
                    if (bFragment == null)
                        bFragment = new BFragment();
                    return bFragment;
                }
                case (INDEX_LINKAREER): {

                    if (linkareerFragment == null)
                        linkareerFragment = new LinkareerFragment();
                    return linkareerFragment;
                }
                case (INDEX_MEALS): {
                    L.Companion.d("mealsFragment check=" + mealsFragment);
                    if (mealsFragment == null)
                        mealsFragment = new MealsFragment();
                    return mealsFragment;

                }
            }

            return null;
        }

        @Override
        public int getCount() {
            return 3;
        }
    }

현재 코드는 프래그먼트 재생성을 막기 위해 제가 사용하던 코드인데 적합하지 않았던것 같습니다. 그때 그때 초기화 해주는 형식으로 변환해서 사용하시는 방법도 추천하고, 그걸 막고 싶다면 FragmentPagerAdapter를 사용하시는걸 추천합니다.

주의사항

FragmentStatePagerAdapter를 사용하면 보통 위의 코드 처럼 사용하면서 화면이 onCreate 됐을때 1회만 프래그먼트를 생성하고 그 후로는 생성된 프래그먼트를 변수처럼 사용했습니다.

그런데 문제는 config의 변화가 있을때 ( 앱을 사용하는 중간에 디바이스 설정에서 앱의 권한을 변경 했거나, 화면을 회전했을 경우 ) 앱이 재실행되는데 기존에 선언했던 FragmentStatePagerAdapter속 getItem이 호출되지 않아 프래그먼트들이 null이 됩니다.

문제가 되지 않을 수 있지만 다수의 프래그먼트를 A 엑티비티에서 관리한다고 하면 오작동 합니다.

예) A 엑티비티에서 유저 정보를 불러와 해당 정보로 다수의 프래그먼트의 ui를 변경해준다. -> null이기 때문에 유저정보가 반영되지 않은 뷰가 보여진다.

방어코드

instantiateItem 메소드를 오버라이드해서 아래와 같이 사용합니다.

  @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            Fragment instantFragment = (Fragment) super.instantiateItem(container, position);
            switch (position) {
                case (INDEX_A): {
                    aFragment = (AFragment) instantFragment;
                    break;
                }

                 case (INDEX_B): {
                    bFragment = (BFragment) instantFragment;
                    break;
                }
            }

            return instantFragment;
        }

 

궁금하신 사항이 있으면 언제든 댓글로 남겨주시면 최대한 빠르게 확인 후 답변 드리겠습니다.

반응형