FragmentStatePagerAdapter, childFragmentManager и ориентация меняют плохую комбинацию?

Вот моя проблема, у меня есть действие, которое включает в себя фрагмент с использованием ViewPager (FragmentStatePagerAdapter), все работает отлично, когда действие загружается в первый раз, но при установке setRetainInstance(true) для родительского фрагмента (тот, с пейджером), и ориентация меняется, это вызывает

java.lang.IllegalStateException: нет активности

При попытке добавить сохраненный фрагмент вот код:

Мероприятия:

public class DetailActivity{

...
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.frame_layout_with_progress_container);

    ...

    // However, if we're being restored from a previous state,
    // then we don't need to do anything and should return or else
    // we could end up with overlapping fragments.
    FragmentManager fm = getSupportFragmentManager();
    if (savedInstanceState != null) {
        Fragment f = fm.findFragmentById(R.id.container);
        if(f instanceof DetailPagerFragment){
            detailPagerFragment = (DetailPagerFragment) f;
        }
    }
}

@Override
protected void onPostResume() {
    super.onPostResume();

    //If fragment is null, create a new instance
    if(detailPagerFragment==null){
        detailPagerFragment =
            DetailContainerFragment.newInstance(details, initialPosition);
    }

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.replace(R.id.container, detailPagerFragment);
    ft.commit();
}

Примечание: я должен сохранить экземпляр фрагмента в onCreate, потому что, когда код достигает onStart, ссылка на этот фрагмент была нулевой (эта проблема не важна, поскольку она как-то связана с NavigationDrawer) , поэтому мне нужно вручную сохранить экземпляр фрагмента.

Схема деятельности:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/container"/>

</RelativeLayout>

ViewPager Fragmentm этот класс расширяется для DetailPagerFragment, который является настраиваемым фрагментом пейджера, он только обертывает общий код для пейджеров (например, просмотр инфляции, использует метод inflateView), поэтому пейджер добавляется во фрагмент, а не непосредственно в активность :

public class DetailContainerFragment extends DetailPagerFragment {

    List<Detail> details;

    public static DetailContainerFragment newInstance(List<Detail> details,int selectedPosition) {
        DetailContainerFragment df = new DetailContainerFragment();
        df.setSelectedPosition(selectedPosition);
        df.setDetails(details);
        return df;
    }

    public void setDetails(List<Detail> details) {
        this.details = details;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }


    /**
     * Inflates the view to be used by this fragment
     *
     * @param inflater
     *  Inflater to use
     * @return Inflated view
     */
    @Override
    public View inflateView(LayoutInflater inflater) {
        return inflater.inflate(R.layout.detail_pager_fragment, null);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        DetailStatePagerAdapter detailStatePagerAdapter = new DetailStatePagerAdapter(getChildFragmentManager());
        setPagerAdapter(detailStatePagerAdapter);
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    private class DetailStatePagerAdapter extends FragmentStatePagerAdapter {

        public DetailStatePagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return DetailFragment.newInstance(details.get(position));
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return details.get(position).getTitle();
        }

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

person JavierSP1209    schedule 23.05.2014    source источник
comment
Как насчет того, чтобы ваша активность и фрагмент не связывались вместе в onStart()? это звучит странно. Может ли это быть основой вашей проблемы?   -  person ILovemyPoncho    schedule 24.05.2014
comment
Фрагмент добавляется в postResume, чтобы избежать java.lang.IllegalStateException: невозможно выполнить это действие после onSaveInstanceState, как описано здесь: androiddesignpatterns.com/2013/08/, это единственный метод, который гарантированно вызывается после восстановления активности.   -  person JavierSP1209    schedule 25.05.2014


Ответы (1)


person    schedule
comment
Спасибо большое! Я провел дни, выясняя, как решить эту проблему. - person nibz; 23.10.2018