4

这是我的问题,我有一个活动,其中包括一个使用(FragmentStatePagerAdapter)具有 ViewPager 的 Fragment,当 Activity 第一次加载时一切正常,但是当将 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();
        }
    }
}
4

1 回答 1

7

ViewPager 中的子片段也有类似的问题。

父片段创建了要与 ViewPager 一起使用的子片段的新实例,而适配器保留了在配置更改之前使用的旧子片段的实例。

在用它初始化适配器之前,我最终清理了 ChildFragmentManager:

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    mPager = (ViewPager) view.findViewById(R.id.pager);

    cleanChildFragments(getChildFragmentManager());

    mPagerAdapter = new MyPagerAdapter(getChildFragmentManager(), getTabFragments());
    mPager.setAdapter(mPagerAdapter);
}

/**
 * This is necessary to have a clean ChildFragmentManager, old fragments might be called otherwise
 * @param childFragmentManager
 */
private void cleanChildFragments(FragmentManager childFragmentManager) {
    List<Fragment> childFragments = childFragmentManager.getFragments();
    if (childFragments != null && !childFragments.isEmpty()) {
        FragmentTransaction ft = childFragmentManager.beginTransaction();
        for (Fragment fragment : childFragments) {
            ft.remove(fragment);
        }
        ft.commit();
    }
}

也许这可以帮助某人...

于 2014-06-25T17:18:06.223 回答