ViewPager с фрагментами, жизненные циклы?

Есть приложение, в нем ViewPager и два фрагмента. Реализуется это так:

public class MainActivity extends FragmentActivity {

    Vector<Fragment> fragments;
    ViewPager viewPager;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

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

        fragments = new Vector<Fragment>();
        fragments.add(Fragment.instantiate(this, Fragment1.class.getName()));
        fragments.add(Fragment.instantiate(this, Fragment2.class.getName()));

        viewPager.setOffscreenPageLimit(fragments.size());
        PagerAdapter pagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), fragments);

        viewPager.setAdapter(pagerAdapter);

        viewPager.setCurrentItem(0);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode==1) {
            ((Fragment1)fragments.get(0)).load();
        }
    }

    class PagerAdapter extends FragmentPagerAdapter implements IconPagerAdapter {

        private List<Fragment> fragments;

        public PagerAdapter(FragmentManager fm, List<Fragment> fragments) {
            super(fm);
            this.fragments = fragments;
        }

        @Override
        public Fragment getItem(int position) {
            return this.fragments.get(position);
        }

        @Override
        public int getCount() {
            return this.fragments.size();
        }

    }

}



В классе Fragment1 у меня есть переменные, которые объявлены как свойства класса и инициализируются внутри метода onCreateView():

public class Fragment1 extends Fragment {

    ArrayList<ListItemObject> listItems = null;
    ArrayAdapter<ListItemObject> mAdapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        listItems = new ArrayList<ListItemObject>();
        mAdapter = new MyAdapter(getActivity(), listItems);
        listView.setAdapter(mAdapter);
    }

    void load() {
            mAdapter.clear();
            ...
    }

}



Проблема вот в чем. Во фрагментах иногда (не слишком часто) mAdapter бывает равным нулю. То есть получается, что фрагмент пересоздается, но без вызова onCreateView(). Мне же нужно, чтобы он вообще не пересоздавался пока приложение запущено. Кроме того, внутри фрагмента используется getActivity(), который иногда возвращает null. Возможно, эти две проблемы связаны. Возможно ли это как-то исправить?
  • Вопрос задан
  • 14752 просмотра
Пригласить эксперта
Ответы на вопрос 6
ara89
@ara89
Используйте код из сэмпла в доках. Не храните ссылки на фрагменты в адаптере.

Чтобы фрагмент не пересоздавался можно вызывать метод setRetainInstance(true)

Если вам нужно находить фрагмент по тэгу, то и создать его можно со своим тэгом с помощью класса FragmentTransaction.
В случае с ViewPager, FragmentPagerAdapter назначает фрагментам свои тэги, это можно увидеть в его исходниках.
Там метод makeFragmentName(int viewId, long id) назначает фрагментам тэги вида:

 private static String makeFragmentName(int viewId, long id) {
        return "android:switcher:" + viewId + ":" + id;
    }

где viewId — id ViewPagera, id — позиция фрагмента.
Соответственно, по этим тэгам можно брать фрагменты из ViewPagera
Ответ написан
Комментировать
recompileme
@recompileme
перенесите определение адаптера и активити в онкриэйт, а не в онкриэйтвью:
Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "init"); dlgs = new ArrayList<ClsVideos>(); adapter = new AdpVideos(getActivity(),dlgs); dlgsSize = 0; offset = 0; activity = getActivity(); }
Ответ написан
recompileme
@recompileme
можно отключить пересоздание фрагмента при смене ориентации активити: android:configChanges=«keyboardHidden|orientation|screenSize»
Ответ написан
Collosteam
@Collosteam
Android кодирую
Попробуй использовать
PagerAdapter pagerAdapter = new PagerAdapter(getChildFragmentManager(), fragments);

вместо
PagerAdapter pagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), fragments);
Ответ написан
bartwell
@bartwell Автор вопроса
То есть можно на выбор — либо сохранять в MainActivity теги созданных фрагментов и в адаптере в getItem() делать findFragmentByTag(), либо в том же getItem() получать каждый раз фрагменты с помощью Fragment.instantiate() и устанавливать для них setRetainInstance(true)? Я правильно понимаю? Если так, то как лучше делать?
Ответ написан
@dmitriy_deomin
Можно попробовать изменить лимит страниц
setOffscreenPageLimit

viewPager.setOffscreenPageLimit(5);
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы