Android 如何在TabHost/ViewPager父片段中恢复子片段

Android 如何在TabHost/ViewPager父片段中恢复子片段,android,android-fragments,android-viewpager,android-tabhost,fragment-tab-host,Android,Android Fragments,Android Viewpager,Android Tabhost,Fragment Tab Host,问题在下面突出显示,第一部分描述了到目前为止的工作情况 我在一个活动中使用多个片段。图的上半部分显示了单个片段,例如,包含一些随机内容的列表。如果我单击某个地方,它将打开关于应用程序片段的。当我单击back时,它再次显示a单个片段。这很好,但这是最简单的部分:) 这是我用来打开新片段的代码 AboutTheAppFragment aboutTheAppFragment = new AboutTheAppFragment(); FragmentTransaction fragmentTrans

问题在下面突出显示,第一部分描述了到目前为止的工作情况

我在一个活动中使用多个片段。图的上半部分显示了单个片段,例如,包含一些随机内容的列表。如果我单击某个地方,它将打开关于应用程序片段的
。当我单击
back
时,它再次显示
a单个片段。这很好,但这是最简单的部分:)

这是我用来打开新片段的代码

AboutTheAppFragment aboutTheAppFragment = new AboutTheAppFragment();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(mContainer.getId(), aboutTheAppFragment, AboutTheAppFragment.class.getName());
fragmentTransaction.addToBackStack(null);
现在我的问题来了 我喜欢显示一个
TabHostPagerFragment
,它使用一个TabHost和一个ViewPager来显示片段,而不是
ASingleFragment
(参见下图)。假设我有两个片段
TabOneFragment
tabtworfragment
,但ViewPager中只显示一个片段。这也很好,我可以简单地在屏幕上滑动,它可以在两个选项卡片段之间切换。但是,如果我单击某个位置打开关于应用片段的
并再次单击
返回
,则片段
选项卡片段
选项卡片段
都不会显示任何内容。如果我旋转设备,它会再次重新加载/恢复碎片,一切正常。因此,我的问题是,如何将
TabOneFragment
tabtworfragment
添加到backbackback,以确保在单击
back
按钮时正确显示它们?注意,当我将
TabOneFragment
设置为
ASingleFragment
时,它的工作原理与场景1类似,然后单击某个位置并再次单击“上一步”。但是当我使用TabHostPagerFragment时,它不起作用

以下是TabHostPagerFragment的一些代码片段:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the tabs pager fragment in the container
    View view = inflater.inflate(R.layout.fragment_tabs_pager, container, false);
    mContainer = container;

    // Set up the TabHost
    mTabHost = (TabHost) view.findViewById(android.R.id.tabhost);
    mTabHost.setup();

    // Set up the ViewPager
    mViewPager = (ViewPager) view.findViewById(R.id.pager);

    return view;
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    // Now initialize the TabsAdapter which will be used to manage the tabs
    mTabsAdapter = new TabsAdapter(activity, mTabHost, mViewPager);

    // Finally add the tabs to the TabsAdapter: meal plan for today and meal plan for the week 
    mTabsAdapter.addTab(mTabHost.newTabSpec("TabOne").setIndicator("TabOne", TabOneFragment.class, null);
    mTabsAdapter.addTab(mTabHost.newTabSpec("TabTwo").setIndicator("TabTwo", TabTwoFragment.class, null);

    if (savedInstanceState != null) {
        // NEVER REACHES THIS CASE
        mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
    }
}
我注意到savedInstanceState始终为空。知道如何修复此问题并将选项卡存储在已保存的实例状态中吗

我将感谢任何帮助

向你问好,迈克尔

编辑:

以下是片段的调用层次结构:

09-25 09:19:25.695: V/TabsPagerParentFragment(1820): onPause
09-25 09:19:25.695: V/TabsPagerParentFragment(1820): onStop
09-25 09:19:25.703: V/TabsPagerParentFragment(1820): onDestroyView
09-25 09:19:25.710: V/AboutTheAppFragment(1820): onAttach
09-25 09:19:25.710: V/AboutTheAppFragment(1820): onCreate: savedInstanceState == null
09-25 09:19:25.710: V/AboutTheAppFragment(1820): onCreateView: savedInstanceState == null
09-25 09:19:25.812: V/AboutTheAppFragment(1820): onViewCreated
09-25 09:19:25.812: V/AboutTheAppFragment(1820): onActivityCreated
09-25 09:19:25.812: V/AboutTheAppFragment(1820): onViewStateRestored
09-25 09:19:25.812: V/AboutTheAppFragment(1820): onStart
09-25 09:19:25.812: V/AboutTheAppFragment(1820): onResume
09-25 09:19:27.304: V/AboutTheAppFragment(1820): onPause
09-25 09:19:27.304: V/AboutTheAppFragment(1820): onStop
09-25 09:19:27.304: V/AboutTheAppFragment(1820): onDestroyView
09-25 09:19:27.304: V/AboutTheAppFragment(1820): onDestroy
09-25 09:19:27.312: V/TabsPagerParentFragment(1820): onCreateView: savedInstanceState == null
09-25 09:19:27.320: V/TabsPagerParentFragment(1820): onViewCreated
09-25 09:19:27.320: V/TabsPagerParentFragment(1820): onActivityCreated
09-25 09:19:27.328: V/TabsPagerParentFragment(1820): onViewStateRestored
09-25 09:19:27.328: V/TabsPagerParentFragment(1820): onStart
09-25 09:19:27.328: V/TabsPagerParentFragment(1820): onResume

在TabHostFragment中,TabOneFragment和TabTwoFragment的构造函数调用:

   setRetainInstance(true);
您当前没有正在“重建”片段状态的内容。当您将单个片段替换为大约ppfragment时,单个片段将被销毁并被遗忘,直到您按下“后退”键,此时系统将重新创建视图继承人,但其中没有任何内容。调用setRetainInstance(true)将告诉系统保留整个片段,包括其数据,以便恢复


onActivityCreated()的saveInstanceState在这里不起作用,它是用于父活动而不是子片段的。

我有一个复杂的布局,一个片段中有3个选项卡,可以切换到其他片段。我意识到,
ViewpagerAdapter
将保持状态,即使您按下home按钮。我的问题是来回切换会使子片段UI视图元素无效并崩溃。关键是不要
new
退出
ViewPagerAdapter
。为适配器添加空检查对我来说很有效。另外,请确保根据您的需要分配
setOffscreenPageLimit()
。另外,据我所知,
setRetainInstance(true)不应用于具有UI的片段,它是为无头片段设计的

在包含选项卡的片段中:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_tab, container, false);
    tabLayout = (TabLayout) view.findViewById(R.id.tablayout);
    viewPager = (ViewPager) view.findViewById(R.id.viewPager);

    //Important!!! Do not fire the existing adapter!!
    if (viewPagerAdapter == null) {
        viewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
        viewPagerAdapter.addFragments(new AFragment(), "A");
        viewPagerAdapter.addFragments(new BFragment(), "B");
        viewPagerAdapter.addFragments(new CFragment(), "C");
    }
    //Allocate retention buffers for three tabs, mandatory
    viewPager.setOffscreenPageLimit(3);
    tabLayout.setupWithViewPager(viewPager);
    viewPager.setAdapter(viewPagerAdapter);

    return view;
}

谢谢你的回复!我试过你的方法,但没用。我还仔细检查了是否调用了所有构造函数。我在帖子中复制了调用层次结构,我想知道为什么从来没有调用过
TabOneFragment
tabtworfragment
的onDestroy方法。有什么想法吗?顺便说一句,我还实现了一个没有TabHost的寻呼机(显示图片),这非常好用。我想这是关于TabHost实现的一些具体问题:-/似乎TabHost没有正确地保留其状态。如果您已经执行了setRetainInstance(true),那么不应该销毁片段,这样就不会调用fragment.onCreate()。但是它们的视图(tabhost)将被销毁,因此调用了onCreateView()。在onActivityCreated()中将选项卡添加到适配器中,但它会创建一个新的选项卡适配器,该选项卡在哪里分配给viewPager?我很想把代码移到onCreateView()中,然后调用mViewPager.setAdapter(),以确保所有这些都一起完成。@NeilS你是怎么解决的?我在viewpager+Fragmetns中也遇到了同样的问题。您的问题是否与原来的问题完全相同?您是否尝试过
setRetainInstance(true)
?因为这个问题已经很老了,所以最好创建一个新的问题-链接到这里,我会看看是否能帮上忙。