Android ViewPager内部片段,如何保留状态?

Android ViewPager内部片段,如何保留状态?,android,android-fragments,fragmentpageradapter,Android,Android Fragments,Fragmentpageradapter,在我的应用程序中,片段活动包含两个片段,片段A和片段B。片段B是一个包含3个片段的视图页面 在我的活动中,为了防止在配置更改时重新创建片段: if(getSupportFragmentManager().findFragmentByTag(MAIN_TAB_FRAGMENT) == null) { getSupportFragmentManager().beginTransaction().replace(R.id.container, new MainTabFragment(), M

在我的应用程序中,片段活动包含两个片段,片段A和片段B。片段B是一个包含3个片段的视图页面

在我的活动中,为了防止在配置更改时重新创建片段:

if(getSupportFragmentManager().findFragmentByTag(MAIN_TAB_FRAGMENT) == null) {
    getSupportFragmentManager().beginTransaction().replace(R.id.container, new MainTabFragment(), MAIN_TAB_FRAGMENT).commit();
}
片段B的代码:

public class MainTabFragment extends Fragment {

    private PagerSlidingTabStrip mSlidingTabLayout;
    private LfPagerAdapter adapter;
    private ViewPager mViewPager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_tab, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {

        this.adapter = new LfPagerAdapter(getChildFragmentManager());

        this.mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
        this.mViewPager.setAdapter(adapter);

        this.mSlidingTabLayout = (PagerSlidingTabStrip) view.findViewById(R.id.sliding_tabs);
        this.mSlidingTabLayout.setViewPager(this.mViewPager);
    }
}
适配器的代码:

public class LfPagerAdapter extends FragmentPagerAdapter {

    private static final int NUM_ITEMS = 3;

    private FragmentManager fragmentManager;

    public LfPagerAdapter(FragmentManager fm) {
        super(fm);
        this.fragmentManager = fm;
    }

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

    @Override
    public Fragment getItem(int position) {
        Log.d("TEST","TEST");
        switch (position) {
            case 1:
                return FragmentC.newInstance();
            case 2:
                return FragmentD.newInstance();
            default:
                return FragmentE.newInstance();
        }
    }
}
我的问题是,我无法保留“查看寻呼机”的状态,因为它的子项在方向更改时会出现碎片

显然,这在每次旋转时都被调用:

this.adapter = new LfPagerAdapter(getChildFragmentManager());
这将导致整个寻呼机被重新创建,对吗?结果

getItem(int position)
将在每次旋转时调用,碎片将从头开始创建并失去其状态:

return FragmentC.newInstance();
我试着用以下方法解决这个问题:

if(this.adapter == null)
    this.adapter = new LfPagerAdapter(getChildFragmentManager());
在onview中创建了,但结果是在旋转时,寻呼机内的碎片被移除


您知道如何在寻呼机中正确保持状态吗?

您需要做两件事来解决此问题:

1) 您应该使用
onCreate
方法而不是
onViewCreated
来实例化
LfPagerAdapter

i、 e:


2) 您需要扩展
FragmentStatePagerAdapter
而不是
FragmentPagerAdapter
Android将在配置时自动重新创建您的活动,而无需此行
Android:configChanges=“keyboardHidden | orientation | screenSize”
在您的清单中,以便您可以处理
onConfiguration
更改自己

唯一的方法是在activityFragement中使用
onSaveInstanceState()
保存viewPager状态(例如当前位置)和需要保存内容的片段

有关如何保存viewpager的当前位置并在配置中还原它的示例

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
            int position = mViewPager.getCurrentItem();
            outState.Int("Key", position );
    }

    @Override //then restore in on onCreate();
    public void onCreated(Bundle savedInstanceState) {
        super.onCreated(savedInstanceState);
        // do stuff
        if (savedInstanceState != null) {
              int  position= savedInstanceState.getInt("Key");
            mViewPager.setCurrentItem(position)
        }
    }
当然,这是一个非常基本的例子

Ps:要在片段中还原,请使用onActivityCreated()而不是onCreate()方法


下面是关于如何保留状态的另一个示例:

我通过在instanceState中保存片段状态(以及选定的寻呼机位置)来实现这一点(由于我现在无法访问Eclipse,所以不知道确切的覆盖)。然后在OnCreate(如果在活动中)或OnCreateView()(如果在片段中),我检查它们是否存在,然后重新创建它们。
fragment
s由
FragmentManager
自动管理和还原,
PagerAdapter
实现旨在保持对它们的持久引用。初始化每个页面时,
getItem()
只会被调用一次。@artworkad:似乎
片段已被保留。你到底想表演什么?您能再描述一下吗?
FragmentPagerAdapter
从不分离
片段
s,因此它们像往常一样由
FragmentManager
自动管理和保留,并且两个适配器都保持对它们的持久引用。保留
片段
实例是没有必要的,事实上,它甚至可能在某些方面干扰保留
视图和/或子
片段
s的状态的语义。海盗992:那么需要做什么来解决问题呢?什么都没有-一开始就没有问题。如果未保留
片段
实例,则应已管理
查看页面
和子
片段
的状态(尽管您可能需要正确设置以保留当前页面)。@corsair992:未保留或保留?我没有理解你的意思。正如我在第一条评论中所说:“保留
片段
实例是没有必要的,事实上,甚至可能在某些方面干扰保留
视图
和/或子
片段
的语义。”。我说的是
setRetainInstance(true)调用
片段
初始化代码。实际上,
ViewPager
管理当前位置本身的保存和恢复,前提是在
视图
状态恢复后在适当的时间设置适配器。我知道这是很久以前的事了,但是@corsair992您能对此进行扩展吗?这听起来正是我所需要的。@D_Steve595:看看最新版本的支持库中的
ViewPager
的源代码,它现在似乎应该能够在所有情况下正确处理位置和适配器状态的持久化。你对此有什么问题吗?谢谢你的回复!我最后提出了一个问题,答案如下:
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
            int position = mViewPager.getCurrentItem();
            outState.Int("Key", position );
    }

    @Override //then restore in on onCreate();
    public void onCreated(Bundle savedInstanceState) {
        super.onCreated(savedInstanceState);
        // do stuff
        if (savedInstanceState != null) {
              int  position= savedInstanceState.getInt("Key");
            mViewPager.setCurrentItem(position)
        }
    }