Подтвердить что ты не робот

Сохранение состояния фрагмента в 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>

Мой вопрос заключается в том, что вместо создания нового экземпляра Fragment каждый раз, когда пользователь выполняет поиск влево и вправо, как мне сохранить состояние фрагмента (для некоторой структуры данных), а затем восстановить его?

демонстрационный файл API, похоже, вообще не содержит кода сохранения состояния.

4b9b3361

Ответ 2

Update: В getItem из MyAdapter вы возвращаете новый экземпляр вашего фрагмента. Android не будет вызывать getItem при каждом ударе. Он вызовет только getItem, чтобы получить новый экземпляр, но будет повторно использовать существующие экземпляры, если они доступны.

О государственной части Демонстрации. Я не могу вам помочь. Я думаю, что здесь применяются обычные методы восстановления состояния в Fragements/Activities, поэтому ничего особенного при загрузке в ViewPager (но я могу ошибаться).

Ответ 3

Если вы переопределите

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

без вызова супер, фрагмент не будет уничтожен и будет повторно использован.

Ответ 4

просто переопределите этот метод в 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);

из вашего кода

Ответ 5

Адаптер должен быть расширен из FragmentStatePagerAdapter вместо FragmentPageAdapter, и адаптер сохранит ссылку с позиции на фрагмент. В родительской активности или фрагменте, set listener OnPageChangeListener для PageIndicator для определения позиции элемента фрагмента был активирован и обновлен соответствующий статус данных.

О состоянии данных элемента фрагмента, я думаю, следует сохранить/восстановить состояние из Activity или Fragement parent.

Адаптер может добавить код следующим образом:

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);
    }
    ...
}

Надеюсь на эту помощь.

Ответ 6

Я споткнулся о какой-то подобной земле... Я хотел сохранить мои фрагменты, сохраненные в моем адаптере, чтобы избежать бесполезной перезагрузки, поскольку у меня было всего 5 фрагментов в FragmentPagerAdapter.

Мне в основном приходилось создавать массив и переопределять метод 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;
}