在ViewPager中保存片段状态

And*_*oob 45 android android-fragments android-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;
    }

}
Run Code Online (Sandbox Code Playgroud)

}

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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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

API演示似乎并不具有任何状态信息保存在代码全部.

Meg*_*ind 117

使用ViewPager.setOffscreenPageLimit()FragmentActivity

ViewPager pager = (ViewPager) findViewById(R.id.viewPager);
pager.setOffscreenPageLimit(2);
Run Code Online (Sandbox Code Playgroud)

查看更多信息如何告诉我的自定义FragmentPagerAdapter停止销毁我的碎片?

  • 当然这不是一个修复,因为它无助于正确保存状态.它只是阻止寻呼机破坏未使用的碎片,有效地将问题推迟到以后.例如,何时旋转设备或暂停/恢复应用程序. (10认同)
  • 非动态视图寻呼机的简单有效的解决方案,因为您将保持片段的状态而不再执行任何操作.如果你不需要太多的内存资源,建议你. (6认同)
  • 这不回答这个问题.你只提供了一个解决方案. (4认同)
  • 救了我的命 :) (2认同)

Jin*_*inu 22

只需在FragmentpagerAdapter中覆盖此方法

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

去掉 super.destroyItem(ViewGroup container, int position, Object object);

从你的代码

  • 你救了我的命 :) (3认同)
  • 好一个 从我这边+1。 (3认同)
  • 完美的作品! (2认同)
  • 谢谢@Jinu,它开始了。 (2认同)

Jer*_*oen 14

更新: 在MyAdapter的getItem中,您将返回Fragment的新实例.Android不会在每次刷卡时调用getItem.它只会调用getItem来获取一个新实例,但只要它们可用,它就会重用现有的实例.

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


小智 13

如果你覆盖

public void destroyItem(View container, int position, Object object)
Run Code Online (Sandbox Code Playgroud)

如果不调用super,片段将不会被销毁并将被重用.

  • 这不是你应该解决问题的方式,而且设计真的很糟糕.请不要这样做,而是花一些时间来了解问题的真正含义以及@ jtietema答案中详述的极其简单的解决方案. (14认同)