在ViewPager中保存片段状态

我尝试了API的示例代码 ,它并没有真正的工作,所以我实现了我自己的:

FragmentPagerSupport

public class FragmentPagerSupport extends FragmentActivity { static final int NUM_ITEMS = 10; MyAdapter mAdapter; ViewPager mPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mAdapter = new MyAdapter(getSupportFragmentManager()); Log.i("Pager", "mAdapter = " + mAdapter.toString()); mPager = (ViewPager)findViewById(R.id.pager); if (mPager == null) Log.i("Pager", "mPager = null"); else Log.i("Pager", "mPager = " + mPager.toString()); Log.i("Pager", "Setting Pager Adapter"); mPager.setAdapter(mAdapter); } public static class MyAdapter extends FragmentPagerAdapter { public MyAdapter(FragmentManager fm) { super(fm); Log.i("Pager", "MyAdapter constructor"); } @Override public int getCount() { Log.i("Pager", "MyAdapter.getCount()"); return NUM_ITEMS; } @Override public Fragment getItem(int position) { Log.i("Pager", "MyAdapter.getItem()"); return TestFragment.newInstance(position); } } public static class TestFragment extends Fragment { public static TestFragment newInstance(int position) { Log.i("Pager", "TestFragment.newInstance()"); TestFragment fragment = new TestFragment(); Bundle args = new Bundle(); args.putInt("position", position); fragment.setArguments(args); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub Log.i("Pager", "TestFragment.onCreateView()"); LinearLayout layout = (LinearLayout)inflater.inflate(R.layout.fragment_item, null); int position = getArguments().getInt("position"); TextView tv = (TextView)layout.findViewById(R.id.text); tv.setText("Fragment # " + position); tv.setTextColor(Color.WHITE); tv.setTextSize(30); return layout; } } 

}

main.xml中

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> 

fragment_item.xml

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/text" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="@string/hello" /> </LinearLayout> 

我的问题是,而不是每次用户左右滑动创build一个新的Fragment实例,如何保存一个片段的状态(某些数据结构),然后恢复它?

API演示似乎没有任何状态信息保存代码。

FragmentActivity使用ViewPager.setOffscreenPageLimit()

 ViewPager pager = (ViewPager) findViewById(R.id.viewPager); pager.setOffscreenPageLimit(2); 

如何告诉我的自定义FragmentPagerAdapter停止销毁我的碎片?

更新:在MyAdapter的getItem中,你返回一个新的Fragment实例。 Android不会在每次滑动时调用getItem。 它只会调用getItem来获取新的实例,但只要可用,就会重用现有的实例。

关于Demo的状态部分。 我帮不了你 我认为在Fragements / Activities中恢复状态的常规技术在这里适用,因此在ViewPager中加载它时没什么特别的(但我可能是错的)。

如果你重写

 public void destroyItem(View container, int position, Object object) 

没有调用超级,片段不会被破坏,将被重用。

只需在FragmentpagerAdapter中覆盖此方法

 @Override public void destroyItem(ViewGroup container, int position, Object object) { // TODO Auto-generated method stub super.destroyItem(ViewGroup container, int position, Object object); } 

删除super.destroyItem(ViewGroup container, int position, Object object);

从你的代码

适配器应该从FragmentStatePagerAdapter扩展而不是FragmentPageAdapter,适配器将保持从位置到片段项的引用。 在活动或片段父项上,为PageIndicator设置监听器OnPageChangeListener,以检测已激活的片段项的位置并更新相关数据的状态。

关于片段项目的数据状态,我认为应该从Activity或Fragement父节点保存/恢复状态。

该适配器可以添加一些代码如下:

 public static class MyAdapter extends FragmentStatePagerAdapter { private SparseArray<TestFragment> mPageReferenceMap = new SparseArray<TestFragment>(); ... @Override public Object instantiateItem(ViewGroup viewGroup, int position) { Object obj = super.instantiateItem(viewGroup, position); //Add the reference when fragment has been create or restore if (obj instanceof TestFragment) { TestFragment f= (TestFragment)obj; mPageReferenceMap.put(position, f); } return obj; } @Override public void destroyItem(ViewGroup container, int position, Object object) { //Remove the reference when destroy it mPageReferenceMap.remove(position); super.destroyItem(container, position, object); } public TestFragment getFragment(int key) { return mPageReferenceMap.get(key); } ... } 

希望这个帮助。

我绊倒了一些类似的地面…我想保留我的片段保存在我的适配器,以避免无用的重新加载,因为我只有5片段在FragmentPagerAdapter

我基本上必须创build一个数组并重写getItem(position)方法:

 private StoryListFragment[] fragmentsArray = new StoryListFragment[getCount()]; public SectionsAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { if(fragmentsArray[position]!=null) return fragmentsArray[position]; StoryListFragment storyListFragment = null; switch(position){ case(0): storyListFragment = StoryListFragment.newInstance(StoriesBank.NEWS); break; case(1): storyListFragment = StoryListFragment.newInstance(StoriesBank.FEATURES); break; case(2): storyListFragment= StoryListFragment.newInstance(StoriesBank.ARTS); break; } fragmentsArray[position] = storyListFragment; return storyListFragment; } @Override public Object instantiateItem(ViewGroup container, int position) { StoryListFragment fragment = (StoryListFragment) super.instantiateItem(container, position); fragmentsArray[position] = fragment; return fragment; }