Сохранение Fragment состояния в ViewPager

голоса
37

Я попробовал образец кода из 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 демо , кажется, не имеют какой - либо информации о состоянии экономии кода на всех.

Задан 26/07/2011 в 19:10
источник пользователем
На других языках...                            


6 ответов

голоса
101

Использование ViewPager.setOffscreenPageLimit()вFragmentActivity

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

Смотри на Как я сказать пользовательский FragmentPagerAdapter , чтобы остановить уничтожение моих фрагментов?

Ответил 11/11/2013 в 08:48
источник пользователем

голоса
13

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

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

Ответил 01/08/2011 в 15:31
источник пользователем

голоса
12

Если переопределить

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

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

Ответил 27/10/2011 в 10:25
источник пользователем

голоса
11

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

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

Ответил 21/01/2015 в 09:53
источник пользователем

голоса
3

Адаптер должен быть увеличен с FragmentStatePagerAdapter вместо FragmentPageAdapter и адаптер будет держать ссылку от позиции к пункту фрагмента. О деятельности или фрагмента родителя, установите слушатель OnPageChangeListener для PageIndicator для определения положения пункта фрагмента активирован и обновление связанного с состоянием данных.

О состоянии данных элемента фрагмента, я думаю, что следует сохранить / восстановить состояние от деятельности или 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);
    }
    ...
}

Надеюсь, что это поможет.

Ответил 05/06/2013 в 17:03
источник пользователем

голоса
0

Я споткнулся о какой - то подобной земле ... Я хотел , чтобы мои фрагменты , сохраненных в моем адаптере , чтобы избежать бесполезной перезарядки , так как я только имел 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;
}
Ответил 25/12/2014 в 03:03
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more