android developer - ViewPager 및 조각-조각의 상태를 저장하는 올바른 방법은 무엇입니까?




offscreenpagelimit compile (9)

FragmentPagerAdapterFragmentPagerAdapter 에 단편을 추가 할 때 단편이 배치 될 특정 위치를 기반으로 특수 태그를 사용합니다. FragmentPagerAdapter.getItem(int position) 은 해당 FragmentPagerAdapter.getItem(int position) 의 프래그먼트가없는 경우에만 호출됩니다. 회전 후에 Android는 이미이 특정 위치에 대한 프래그먼트를 작성 / 저장 했으므로 새로운 위치를 만들기보다는 FragmentManager.findFragmentByTag() 를 사용하여 다시 연결하려고합니다. 이 모든 것은 FragmentPagerAdapter 사용할 때 무료이며, 일반적으로 조각 초기화 코드를 getItem(int) 메소드 내에 포함하는 것이 일반적입니다.

FragmentPagerAdapter 사용하지 않더라도 Activity.onCreate(Bundle) 에서 매번 새 프래그먼트를 만드는 것은 좋지 않습니다. 아시다시피 조각이 FragmentManager에 추가되면 회전 후에 조각이 다시 만들어지며 다시 추가 할 필요가 없습니다. 이렇게하면 조각으로 작업 할 때 오류가 발생하는 일반적인 원인이됩니다.

파편으로 작업 할 때 일반적인 접근법은 다음과 같습니다.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ...

    CustomFragment fragment;
    if (savedInstanceState != null) {
        fragment = (CustomFragment) getSupportFragmentManager().findFragmentByTag("customtag");
    } else {
        fragment = new CustomFragment();
        getSupportFragmentManager().beginTransaction().add(R.id.container, fragment, "customtag").commit(); 
    }

    ...

}

FragmentPagerAdapter 사용할 때는 조각 관리를 어댑터에 맡기고 위의 단계를 수행 할 필요가 없습니다. 기본적으로 하나의 Fragment를 현재 위치의 앞과 뒤에 미리로드합니다 (단, FragmentStatePagerAdapter 사용하지 않는 이상 FragmentStatePagerAdapter 는 파손되지 않습니다). 이것은 ViewPager.setOffscreenPageLimit(int) 의해 제어됩니다. 이 때문에 어댑터 외부의 조각에 대한 메서드를 직접 호출해도 유효하지 않을 수 있기 때문에 유효하지 않을 수 있습니다.

긴 이야기를 짧게 putFragment 위해 putFragment 를 사용하여 이후에 참조를 얻을 수있는 솔루션이 너무 미친 것은 아니며 어쨌든 (위에서) 파편을 사용하는 일반적인 방법과 다르지 않습니다. 프래그먼트가 어댑터에 의해 추가되고 개인적으로 추가되지 않기 때문에 다른 방법으로 참조를 얻는 것은 어렵습니다. offscreenPageLimit 은 원하는 조각을 항상로드 할 수있을만큼 충분히 높은지 확인하십시오. 이는 ViewPager의 느린 로딩 기능을 우회하지만 애플리케이션에 원하는 것처럼 보입니다.

또 다른 접근법은 FragmentPageAdapter.instantiateItem(View, int) 를 오버라이드하고 반환하기 전에 슈퍼 콜에서 반환 된 프래그먼트에 대한 참조를 저장하는 것입니다 (이미 존재한다면 프래그먼트를 찾는 로직을가집니다).

더 자세한 그림을 보려면 FragmentPagerAdapter (short) 및 ViewPager (long)의 소스 중 일부를 살펴보십시오.

프래그먼트는 UI 로직을 일부 모듈로 분리하는 데 매우 유용합니다. ViewPager 의 라이프 사이클은 여전히 ​​나에게 안개입니다. 따라서 전문가의 생각은 나쁘다.

편집하다

아래 바보 솔루션을 참조하십시오 ;-)

범위

주요 액티비티에는 조각이있는 ViewPager 가 있습니다. 이러한 조각은 다른 (submain) 활동을 위해 약간 다른 논리를 구현할 수 있으므로 조각의 데이터는 활동 내부의 콜백 인터페이스를 통해 채워집니다. 그리고 첫 발사에서는 모든 것이 잘 작동하지만 ...!

문제

액티비티가 다시 생성되면 (예 : 오리엔테이션 변경) ViewPager 의 프래그먼트를 수행하십시오. 이 코드는 액티비티가 생성 될 때마다 조각과 같은 새로운 ViewPager 프래그먼트 어댑터를 생성하려고 시도하지만 FragmentManager는 이미 이러한 모든 프래그먼트를 이미 어딘가에 저장하고 있다고 말합니다 (어디에서?). 그것들을위한 레크리에이션 메커니즘을 시작합니다. 따라서 레크리에이션 메커니즘은 Activity의 구현 된 메소드를 통해 데이터를 시작하기 위해 콜백 인터페이스 호출로 "이전"프래그먼트의 onAttach, onCreateView 등을 호출합니다. 그러나이 메소드는 Activity의 onCreate 메소드를 통해 새로 생성 된 프래그먼트를 가리 킵니다.

발행물

어쩌면 나는 잘못된 패턴을 사용하고 있을지도 모르지만 안드로이드 3 프로 서적은 그다지 중요하지 않습니다. 그러니 제발 , 제게 한 두 펀치를주고 옳은 방법을 가르쳐 주세요 . 많은 감사합니다!

암호

주요 활동

public class DashboardActivity extends BasePagerActivity implements OnMessageListActionListener {

private MessagesFragment mMessagesFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
    Logger.d("Dash onCreate");
    super.onCreate(savedInstanceState);

    setContentView(R.layout.viewpager_container);
    new DefaultToolbar(this);

    // create fragments to use
    mMessagesFragment = new MessagesFragment();
    mStreamsFragment = new StreamsFragment();

    // set titles and fragments for view pager
    Map<String, Fragment> screens = new LinkedHashMap<String, Fragment>();
    screens.put(getApplicationContext().getString(R.string.dashboard_title_dumb), new DumbFragment());
    screens.put(getApplicationContext().getString(R.string.dashboard_title_messages), mMessagesFragment);

    // instantiate view pager via adapter
    mPager = (ViewPager) findViewById(R.id.viewpager_pager);
    mPagerAdapter = new BasePagerAdapter(screens, getSupportFragmentManager());
    mPager.setAdapter(mPagerAdapter);

    // set title indicator
    TitlePageIndicator indicator = (TitlePageIndicator) findViewById(R.id.viewpager_titles);
    indicator.setViewPager(mPager, 1);

}

/* set of fragments callback interface implementations */

@Override
public void onMessageInitialisation() {

    Logger.d("Dash onMessageInitialisation");
    if (mMessagesFragment != null)
        mMessagesFragment.loadLastMessages();
}

@Override
public void onMessageSelected(Message selectedMessage) {

    Intent intent = new Intent(this, StreamActivity.class);
    intent.putExtra(Message.class.getName(), selectedMessage);
    startActivity(intent);
}

BasePagerActivity 일컬어 도우미

public class BasePagerActivity extends FragmentActivity {

BasePagerAdapter mPagerAdapter;
ViewPager mPager;
}

어댑터

public class BasePagerAdapter extends FragmentPagerAdapter implements TitleProvider {

private Map<String, Fragment> mScreens;

public BasePagerAdapter(Map<String, Fragment> screenMap, FragmentManager fm) {

    super(fm);
    this.mScreens = screenMap;
}

@Override
public Fragment getItem(int position) {

    return mScreens.values().toArray(new Fragment[mScreens.size()])[position];
}

@Override
public int getCount() {

    return mScreens.size();
}

@Override
public String getTitle(int position) {

    return mScreens.keySet().toArray(new String[mScreens.size()])[position];
}

// hack. we don't want to destroy our fragments and re-initiate them after
@Override
public void destroyItem(View container, int position, Object object) {

    // TODO Auto-generated method stub
}

}

파편

public class MessagesFragment extends ListFragment {

private boolean mIsLastMessages;

private List<Message> mMessagesList;
private MessageArrayAdapter mAdapter;

private LoadMessagesTask mLoadMessagesTask;
private OnMessageListActionListener mListener;

// define callback interface
public interface OnMessageListActionListener {
    public void onMessageInitialisation();
    public void onMessageSelected(Message selectedMessage);
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    // setting callback
    mListener = (OnMessageListActionListener) activity;
    mIsLastMessages = activity instanceof DashboardActivity;

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    inflater.inflate(R.layout.fragment_listview, container);
    mProgressView = inflater.inflate(R.layout.listrow_progress, null);
    mEmptyView = inflater.inflate(R.layout.fragment_nodata, null);
    return super.onCreateView(inflater, container, savedInstanceState);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    // instantiate loading task
    mLoadMessagesTask = new LoadMessagesTask();

    // instantiate list of messages
    mMessagesList = new ArrayList<Message>();
    mAdapter = new MessageArrayAdapter(getActivity(), mMessagesList);
    setListAdapter(mAdapter);
}

@Override
public void onResume() {
    mListener.onMessageInitialisation();
    super.onResume();
}

public void onListItemClick(ListView l, View v, int position, long id) {
    Message selectedMessage = (Message) getListAdapter().getItem(position);
    mListener.onMessageSelected(selectedMessage);
    super.onListItemClick(l, v, position, id);
}

/* public methods to load messages from host acitivity, etc... */
}

해결책

바보 같은 해결책은 putFragment를 사용하여 onSaveInstanceState (호스트 활동)의 조각을 저장하고 getFragment를 통해 onCreate 안에 가져 오는 것입니다. 그러나 나는 이상하게 느껴져서 일이 그렇게 작동해서는 안된다. 아래 코드를 보라.

    @Override
protected void onSaveInstanceState(Bundle outState) {

    super.onSaveInstanceState(outState);
    getSupportFragmentManager()
            .putFragment(outState, MessagesFragment.class.getName(), mMessagesFragment);
}

protected void onCreate(Bundle savedInstanceState) {
    Logger.d("Dash onCreate");
    super.onCreate(savedInstanceState);

    ...
    // create fragments to use
    if (savedInstanceState != null) {
        mMessagesFragment = (MessagesFragment) getSupportFragmentManager().getFragment(
                savedInstanceState, MessagesFragment.class.getName());
                StreamsFragment.class.getName());
    }
    if (mMessagesFragment == null)
        mMessagesFragment = new MessagesFragment();
    ...
}

내 솔루션은 매우 무례하지만 작동합니다. super.onSaveInstanceState() , 보존 된 데이터에서 동적으로 생성 된 내 조각 인 경우 PageAdapter super.onSaveInstanceState() 를 호출하기 전에 PageAdapter 에서 모든 조각을 제거한 다음 작업 생성시 다시 만듭니다.

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putInt("viewpagerpos", mViewPager.getCurrentItem() );
    mSectionsPagerAdapter.removeAllfragments();
    super.onSaveInstanceState(outState);
}

onDestroy() 에서 제거 할 수 없습니다. 그렇지 않으면이 예외가 발생합니다.

java.lang.IllegalStateException: onSaveInstanceState 이후에이 작업을 수행 할 수 없습니다 java.lang.IllegalStateException:

다음은 페이지 어댑터의 코드입니다.

public void removeAllfragments()
{
    if ( mFragmentList != null ) {
        for ( Fragment fragment : mFragmentList ) {
            mFm.beginTransaction().remove(fragment).commit();
        }
        mFragmentList.clear();
        notifyDataSetChanged();
    }
}

파편이 생성 된 후에 만 ​​현재 페이지를 저장하고 onCreate() 복원합니다.

if (savedInstanceState != null)
    mViewPager.setCurrentItem( savedInstanceState.getInt("viewpagerpos", 0 ) );  

나는 antonyt놀라운 대답FragmentPageAdapter.instantiateItem(View, int) 를 오버라이드 FragmentPageAdapter.instantiateItem(View, int) override FragmentPageAdapter.instantiateItem(View, int) 하여 생성 된 Fragments 대한 참조를 저장하는 방법을 설명하는 솔루션을 제공하여 나중에 작업 할 수 있도록하고 싶습니다. 이것은 또한 FragmentStatePagerAdapter 와 함께 작동해야합니다. 자세한 내용은 메모를 참조하십시오.

다음은 Fragments 에 설정된 내부 tags 에 의존하지 않는 FragmentPagerAdapter 에 의해 반환 된 FragmentPagerAdapter 대한 참조를 얻는 간단한 예제입니다. 핵심은 instantiateItem() 을 재정의하고 getItem() 대신 에 참조를 저장하는 입니다.

public class SomeActivity extends Activity {
    private FragmentA m1stFragment;
    private FragmentB m2ndFragment;

    // other code in your Activity...

    private class CustomPagerAdapter extends FragmentPagerAdapter {
        // other code in your custom FragmentPagerAdapter...

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

        @Override
        public Fragment getItem(int position) {
            // Do NOT try to save references to the Fragments in getItem(),
            // because getItem() is not always called. If the Fragment
            // was already created then it will be retrieved from the FragmentManger
            // and not here (i.e. getItem() won't be called again).
            switch (position) {
                case 0:
                    return new FragmentA();
                case 1:
                    return new FragmentB();
                default:
                    // This should never happen. Always account for each position above
                    return null;
            }
        }

        // Here we can finally safely save a reference to the created
        // Fragment, no matter where it came from (either getItem() or
        // FragmentManger). Simply save the returned Fragment from
        // super.instantiateItem() into an appropriate reference depending
        // on the ViewPager position.
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
            // save the appropriate reference depending on position
            switch (position) {
                case 0:
                    m1stFragment = (FragmentA) createdFragment;
                    break;
                case 1:
                    m2ndFragment = (FragmentB) createdFragment;
                    break;
            }
            return createdFragment;
        }
    }

    public void someMethod() {
        // do work on the referenced Fragments, but first check if they
        // even exist yet, otherwise you'll get an NPE.

        if (m1stFragment != null) {
            // m1stFragment.doWork();
        }

        if (m2ndFragment != null) {
            // m2ndFragment.doSomeWorkToo();
        }
    }
}

또는 Fragments 대한 클래스 멤버 변수 / 참조 대신 tags 사용하여 작업하려는 경우 FragmentPagerAdapter 에서 설정 한 tags 동일한 방식으로 가져올 수 있습니다. 참고 : FragmentPagerAdapter 에는 tags 설정하지 않으므로 FragmentStatePagerAdapter 에는 적용되지 않습니다. 그것의 Fragments .

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
    // get the tags set by FragmentPagerAdapter
    switch (position) {
        case 0:
            String firstTag = createdFragment.getTag();
            break;
        case 1:
            String secondTag = createdFragment.getTag();
            break;
    }
    // ... save the tags somewhere so you can reference them later
    return createdFragment;
}

이 메소드는 FragmentPagerAdapter 설정 한 내부 tag 를 모방 한 것이 아니라 대신 적절한 API를 사용하여 검색합니다. SupportLibrary 의 차후 버전에서 tag 변경 되더라도 여전히 안전합니다.

Activity 디자인에 따라 Activity 하려는 Fragments 가 아직 존재하지 않거나 존재하지 않을 수 있으므로 참조를 사용하기 전에 null 체크를 수행해야합니다.

또한, 대신 FragmentStatePagerAdapter 를 사용하고 있다면, 당신은 당신의 Fragments 대한 하드 참조를 유지하기를 원하지 않을 것입니다. 왜냐하면 이들 중 많은 부분과 하드 참조가 그들을 불필요하게 메모리에 유지할 수 있기 때문입니다. 대신 WeakReference 변수에 표준 참조 목록 대신 Fragment 참조를 저장하십시오. 이렇게 :

WeakReference<Fragment> m1stFragment = new WeakReference<Fragment>(createdFragment);
// ...and access them like so
Fragment firstFragment = m1stFragment.get();
if (firstFragment != null) {
    // reference hasn't been cleared yet; do work...
}

나는이 간단하고 우아한 해결책을 생각해 냈다. 액티비티는 Fragments를 생성하는 역할을 담당하고 있으며, Adapter가 그것들을 제공한다고 가정합니다.

이것은 어댑터의 코드입니다 ( mFragments 가 Activity에 의해 유지 관리되는 프래그먼트의 목록이라는 사실을 제외하고는 이상한 점은 없습니다)

class MyFragmentPagerAdapter extends FragmentStatePagerAdapter {

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

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    @Override
    public int getCount() {
        return mFragments.size();
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        TabFragment fragment = (TabFragment)mFragments.get(position);
        return fragment.getTitle();
    }
} 

이 스레드의 모든 문제는 "오래된"조각의 참조를 얻고 있으므로이 코드를 Activity의 onCreate에서 사용합니다.

    if (savedInstanceState!=null) {
        if (getSupportFragmentManager().getFragments()!=null) {
            for (Fragment fragment : getSupportFragmentManager().getFragments()) {
                mFragments.add(fragment);
            }
        }
    }

물론 필요한 경우이 코드를 더 세밀하게 조정할 수 있습니다 (예 : 조각이 특정 클래스의 인스턴스인지 확인).


누군가가 자신의 FragmentStatePagerAdapter에 문제가 발생하여 조각의 상태를 제대로 복원하지 못하는 경우 ... 즉 FragmentStatePagerAdapter가 새로운 Fragment를 상태에서 복원하는 대신 생성하는 중입니다.

ViewPager.setAdapeter(fragmentStatePagerAdapter) 를 호출하기 전에 ViewPager.setOffscreenPageLimit() 을 호출해야합니다.

ViewPager.setOffscreenPageLimit() 을 호출하면 ViewPager는 즉시 어댑터를보고 해당 프래그먼트를 가져옵니다. 이는 ViewPager가 savedInstanceState에서 Fragments를 복원 할 수 있기 전에 발생할 수 있습니다. 따라서 새로운 Fragment가 새로 추가되었으므로 SavedInstanceState에서 다시 초기화 할 수 없습니다.


나는 약간 다른 경우에 대한 대체 솔루션을 제공하기를 원한다. 왜냐하면 많은 검색 결과가 나에게이 스레드로 이어지고 있기 때문이다.

내 경우 - 동적으로 페이지를 생성 / 추가하고 ViewPager로 슬라이딩하지만, 회전 할 때 (onConfigurationChange) 물론 OnCreate가 다시 호출되기 때문에 새로운 페이지로 끝납니다. 그러나 회전하기 전에 작성된 모든 페이지에 대한 참조를 유지하려고합니다.

문제 - 내가 만든 각 프래그먼트에 대한 고유 식별자가 없으므로 참조 할 수있는 유일한 방법은 순환 / 구성 변경 후에 복원 할 Array의 참조를 어떻게 든 저장하는 것이 었습니다.

해결 방법 - 핵심 개념은 Activity (Fragments를 표시)가 기존 Fragments에 대한 참조 배열을 관리하도록하는 것입니다.이 작업은 onSaveInstanceState에서 Bundles를 사용할 수 있기 때문에

public class MainActivity extends FragmentActivity

그래서이 활동 내에서 개인 회원이 공개 페이지를 추적 할 것을 선언합니다.

private List<Fragment> retainedPages = new ArrayList<Fragment>();

onSaveInstanceState가 호출되고 onCreate에 복원 될 때마다 업데이트됩니다.

@Override
protected void onSaveInstanceState(Bundle outState) {
    retainedPages = _adapter.exportList();
    outState.putSerializable("retainedPages", (Serializable) retainedPages);
    super.onSaveInstanceState(outState);
}

... 일단 저장되면 검색 할 수 있습니다 ...

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (savedInstanceState != null) {
        retainedPages = (List<Fragment>) savedInstanceState.getSerializable("retainedPages");
    }
    _mViewPager = (CustomViewPager) findViewById(R.id.viewPager);
    _adapter = new ViewPagerAdapter(getApplicationContext(), getSupportFragmentManager());
    if (retainedPages.size() > 0) {
        _adapter.importList(retainedPages);
    }
    _mViewPager.setAdapter(_adapter);
    _mViewPager.setCurrentItem(_adapter.getCount()-1);
}

이것들은 주요 액티비티에 필요한 변경 사항 이었기 때문에, FragmentPagerAdapter 내의 멤버와 메소드가 필요했습니다.

public class ViewPagerAdapter extends FragmentPagerAdapter

동일한 구조 (MainActivity에서 위에 보여지는 것과 같이)

private List<Fragment> _pages = new ArrayList<Fragment>();

이 동기화 (onSaveInstanceState에서 위에 사용 된 것처럼)는 특히 메소드에 의해 지원됩니다

public List<Fragment> exportList() {
    return _pages;
}

public void importList(List<Fragment> savedPages) {
    _pages = savedPages;
}

그리고 마침내, 프래그먼트 클래스에서

public class CustomFragment extends Fragment

이 모든 작업을 수행하기 위해 먼저 두 가지 변경 사항이있었습니다.

public class CustomFragment extends Fragment implements Serializable

그리고 나서 이것을 onCreate에 추가하면 Fragments가 파기되지 않습니다.

setRetainInstance(true);

나는 여전히 단편과 안드로이드 라이프 사이클에서 머리를 감싸는 과정에있다. 따라서이 방법에서는 중복성 / 비 효율성이있을 수있다. 하지만 그것은 저에게 효과적이며, 제 경우와 비슷한 다른 사람들에게 도움이되기를 바랍니다.


귀하의 질문에 대한 비교적 쉬운 또 다른 해결책을 찾았습니다.

FragmentPagerAdapter 소스 코드 에서 볼 수 있듯이 FragmentPagerAdapter가 관리하는 FragmentPagerAdapterFragmentManager 에 다음 태그를 사용하여 생성 된 태그 아래에 저장됩니다.

String tag="android:switcher:" + viewId + ":" + index;

viewIdcontainer.getId() 이고, containerViewPager 인스턴스입니다. index 는 프래그먼트의 위치입니다. 따라서 개체 ID를 outState 저장할 수 있습니다.

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("viewpagerid" , mViewPager.getId() );
}

@Override
    protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);
    if (savedInstanceState != null)
        viewpagerid=savedInstanceState.getInt("viewpagerid", -1 );  

    MyFragmentPagerAdapter titleAdapter = new MyFragmentPagerAdapter (getSupportFragmentManager() , this);        
    mViewPager = (ViewPager) findViewById(R.id.pager);
    if (viewpagerid != -1 ){
        mViewPager.setId(viewpagerid);
    }else{
        viewpagerid=mViewPager.getId();
    }
    mViewPager.setAdapter(titleAdapter);

이 프래그먼트와 통신하려면 FragmentManager 에서 다음과 같이 얻을 수 있습니다.

getSupportFragmentManager().findFragmentByTag("android:switcher:" + viewpagerid + ":0")

BasePagerAdapter 는 무엇입니까? ViewPager 에서 더 이상 필요하지 않은 조각 (이전) 또는 상태 저장 (후자) 중 하나를 유지할 것인지 (다시 ViewPager , 표준 페이지 어댑터 중 하나 인 FragmentPagerAdapter 또는 FragmentStatePagerAdapter 중 하나를 사용해야합니다. 필요한 경우 다시 생성됩니다.

ViewPager 를 사용하기위한 샘플 코드는 here 에서 찾을 수 here

프레임 워크의 FragmentManager 가 상태를 저장하고 호출기가 만든 모든 활성 단편을 복원하기 때문에 활동 인스턴스에서 뷰 페이지의 단편을 관리하는 것은 약간 복잡합니다. 이 모든 것이 실제로 의미하는 것은 초기화 할 때 어댑터가 복원 된 조각이 무엇이든 상관없이 다시 연결해야한다는 것입니다. FragmentPagerAdapter 또는 FragmentStatePagerAdapter 코드를 보면 어떻게 수행되는지 확인할 수 있습니다.


/values/integers.xml에 정수 리소스 ID를 만듭니다.

<integer name="page1">1</integer>
<integer name="page2">2</integer>
<integer name="page3">3</integer>

그런 다음 PagerAdapter getItem 함수에서 다음을 수행합니다.

public Fragment getItem(int position) {

        Fragment fragment = null;

        if (position == 0) {
            fragment = FragmentOne.newInstance();
            mViewPager.setTag(R.integer.page1,fragment);

        }
        else if (position == 1) {

            fragment = FragmentTwo.newInstance();
            mViewPager.setTag(R.integer.page2,fragment);

        } else if (position == 2) {

            fragment = FragmentThree.newInstance();
            mViewPager.setTag(R.integer.page3,fragment);

        }

        return fragment;
        }

그런 다음 액티비티에서이 함수를 작성하여 조각 참조를 가져옵니다.

private Fragment getFragmentByPosition(int position) {
    Fragment fragment = null;

    switch (position) {
        case 0:
            fragment = (Fragment) mViewPager.getTag(R.integer.page1);
            break;

        case 1:

            fragment = (Fragment) mViewPager.getTag(R.integer.page2);
            break;

        case 2:
            fragment = (Fragment) mViewPager.getTag(R.integer.page3);
            break;
            }

            return fragment;
    }

위의 함수를 호출하여 조각 참조를 가져 와서 사용자 지정 조각에 캐스팅합니다.

Fragment fragment = getFragmentByPosition(position);

        if (fragment != null) {
                    FragmentOne fragmentOne = (FragmentOne) fragment;
                    }




android design-patterns android-fragments android-viewpager