Отображать fragment просмотра в fragmentе

У меня есть fragment, который содержит ViewPager. ViewPager связан с адаптером, который содержит набор fragmentов.

При загрузке родительского fragmentа мне встречается IllegalStateException с сообщением: java.lang.IllegalStateException: Recursive entry to executePendingTransactions .

Некоторые исследования привели меня к выводу, что система не может отображать fragmentы внутри другого fragmentа, ОДНАКО, похоже, есть некоторые признаки того, что это можно сделать именно с использованием ViewPager ( ошибка в ViewPager, использующая его с другим fragmentом ).

Фактически, если я добавлю кнопку в родительский fragment, который вызывает mPager.setAdapter(mAdapter) на моем ViewPager при нажатии, то ViewPager успешно загружается. Это не идеально.

Затем проблема должна быть связана с жизненным циклом fragmentа. Поэтому мой вопрос заключается в следующем: кто-нибудь еще нашел способ обойти эту проблему, и если да, то как?

Есть ли способ отложить настройку адаптера на ViewPager до момента транзакции fragmentа?

Вот мой родительский fragment кода:

  @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.team_card_master, container, false); mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager); final Button button = (Button)mView.findViewById(R.id.load_viewpager_button); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mViewPager.setAdapter(mAdapter); button.setVisibility(View.GONE); } }); mAdapter = new ViewPagerAdapter(getFragmentManager()); // mViewPager.setAdapter(mAdapter); return mView; } 

И адаптер:

 public class ViewPagerAdapter extends FragmentPagerAdapter { public ViewPagerAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { if (mCursor == null) return 0; else return mCursor.getCount(); } @Override public Fragment getItem(int position) { Bundle b = createBundle(position, mCursor); return TeamCardFragment.newInstance(b); } } 

    8 Solutions collect form web for “Отображать fragment просмотра в fragmentе”

    используйте AsyncTask для установки адаптера для viewPager. Меня устраивает. AsyncTask должен сделать исходный fragment завершенным его переходом. а затем мы идем с fragmentами viewPager, в основном, чтобы избежать рекурсии.

      @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.team_card_master, container, false); mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager); final Button button = (Button)mView.findViewById(R.id.load_viewpager_button); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mViewPager.setAdapter(mAdapter); button.setVisibility(View.GONE); } }); mAdapter = new ViewPagerAdapter(getFragmentManager()); new setAdapterTask().execute(); return mView; } private class setAdapterTask extends AsyncTask{ protected Void doInBackground(Void... params) { return null; } @Override protected void onPostExecute(Void result) { mViewPager.setAdapter(mAdapter); } } 

    Jords, я думаю, вы можете использовать FragmentStatePagerAdapter вместо FragmentPageAdapter . Он удалит fragmentы для вас.

    PS. Извините за использование ответа вместо комментария, но моя репутация слишком низкая.

    Я просто столкнулся с этой проблемой. У меня был Fragment который должен был содержать ViewPager of Fragments . Когда я собрал еще один Fragment поверх моего ViewPagerFragment , а затем ударил обратно, я получил бы IllegalStateException . После проверки журналов (при укладке нового Fragment ) я обнаружил, что мой ViewPagerFragment будет использовать методы жизненного цикла, чтобы остановить и уничтожить, однако его дочерние Fragments в ViewPager останутся в onResume . Я понял, что Fragments детей должен управляться FragmentManager для ViewPagerFragment , а не FragmentManager Activity .

    В то время я понял, что ответы на них касались ограничений Fragments не могут иметь детей. Однако теперь, когда в последней библиотеке поддержки есть поддержка вложения Fragment , вам больше не нужно взламывать настройку адаптера для вашего ViewPager , и передача getChildFragmentManager() – это все, что вам нужно. До сих пор это отлично работало для меня.

     @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.team_card_master, container, false); mViewPager = (ViewPager) mView.findViewById(R.id.team_card_master_view_pager); mAdapter = new ViewPagerAdapter(getChildFragmentManager()); mViewPager.setAdapter(mAdapter); return mView; } 

    Я использовал Handler.post() для установки адаптера вне транзакции оригинального fragmentа:

     @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mHandler.post(new Runnable() { @Override public void run() { mViewPager.setAdapter(mAdapter); } }); } 

    Я столкнулся с этой проблемой при попытке инициализировать адаптер viewPager на вкладке TabIndicator в ViewCreated. Прочитав об этом в сети, я понял, что это может быть только потому, что fragment еще не добавлен в эту деятельность. Поэтому я переместил код инициализации в onStart () fragmentа, это должно решить вашу проблему. Но не для меня, я снова получал такую ​​же проблему.

    Но это было из-за того, что в моем коде я пытался обходить обычное асинхронное выполнение ожидающей задачи, явно вызывая executePendingTransactions (), после блокировки, что все работает хорошо

    При загрузке родительского fragmentа мне встречается исключение IllegalStateException с сообщением: java.lang.IllegalStateException: рекурсивная запись в executePendingTransactions.

    Некоторые исследования привели меня к выводу, что система не может отображать fragmentы внутри другого fragmentа, ОДНАКО, похоже, есть некоторые признаки того, что это можно сделать именно с использованием ViewPager (ошибка в ViewPager, использующая его с другим fragmentом ).

    set Id для ViewPager явно.

      @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mView = inflater.inflate(R.layout.team_card_master, container, false); mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager); mViewPager.setId(100); final Button button = (Button)mView.findViewById(R.id.load_viewpager_button); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mViewPager.setAdapter(mAdapter); button.setVisibility(View.GONE); } }); mAdapter = new ViewPagerAdapter(getFragmentManager()); mViewPager.setAdapter(mAdapter); return mView; } 

    Вы можете использовать id в своих xml-ресурсах вместо магического номера 100.

        

    и setId (R.Id_For_ViewPager).

    Подробнее см. Источник FragmentManager.java.

    https://github.com/android/platform_frameworks_support/blob/master/v4/java/android/support/v4/app/FragmentManager.java#L900

    Или смотрите эту страницу (японский). Первоначальная идея от нее, на самом деле, не я. http://y-anz-m.blogspot.jp/2012/04/androidfragment-viewpager-id.html

    Используя этот shiny пост Томаса Амсслера: http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part-ii.html

    Iv’e создал адаптер, который можно использовать для создания всех типов fragmentов. Сам адаптер выглядит так:

     public abstract class EmbeddedAdapter extends FragmentStatePagerAdapter { private SparseArray> mPageReferenceMap = new SparseArray>(); private ArrayList mTabTitles; public abstract Fragment initFragment(int position); public EmbeddedAdapter(FragmentManager fm, ArrayList tabTitles) { super(fm); mTabTitles = tabTitles; } @Override public Object instantiateItem(ViewGroup viewGroup, int position) { mPageReferenceMap.put(Integer.valueOf(position), new WeakReference(initFragment(position))); return super.instantiateItem(viewGroup, position); } @Override public int getCount() { return mTabTitles.size(); } @Override public CharSequence getPageTitle(int position) { return mTabTitles.get(position); } @Override public Fragment getItem(int pos) { return getFragment(pos); } @Override public void destroyItem(ViewGroup container, int position, Object object) { super.destroyItem(container, position, object); mPageReferenceMap.remove(Integer.valueOf(position)); } public Fragment getFragment(int key) { WeakReference weakReference = mPageReferenceMap.get(key); if (null != weakReference) { return (Fragment) weakReference.get(); } else { return null; } } @Override public int getItemPosition(Object object) { return POSITION_NONE; } 

    }

    Чтобы использовать адаптер, вам нужно будет сделать следующее:

     private void setAdapter() { if(mAdapter == null) mAdapter = new EmbeddedAdapter(getActivity().getSupportFragmentManager(), mTabTitles) { @Override public Fragment initFragment(int position) { Fragment fragment; if(position == 0){ // A start fragment perhaps? fragment = StartFragment.newInstance(mBlocks); }else{ // Some other fragment fragment = PageFragment.newInstance(mCategories.get((position))); } return fragment; } }; // Have to set the adapter in a handler Handler handler = new Handler(); handler.post(new Runnable() { @Override public void run() { mViewPager.setVisibility(View.VISIBLE); mPagerTabStrip.setVisibility(View.VISIBLE); mAdapter.notifyDataSetChanged(); } }); } 

    Обратите внимание, что все fragmentы используют:

     setRetainInstance(true); 

    Согласно документации: https://developer.android.com/reference/android/app/Fragment.html#getChildFragmentManager ()

    Если вы хотите управлять fragmentом вложенности, вы должны использовать getChildFragmentManager вместо getFragmentManager .

    Давайте будем гением компьютера.