Android 恢复时,不会恢复ViewPager中的片段视图

Android 恢复时,不会恢复ViewPager中的片段视图,android,android-fragments,android-tabs,Android,Android Fragments,Android Tabs,我已经设置了ActionBar选项卡。它由4个选项卡组成。一切都很好,直到我离开TabbedFragment并返回 我创建如下选项卡: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final ActionBar actionBar = getActionBar(); tabs = Lis

我已经设置了ActionBar选项卡。它由4个选项卡组成。一切都很好,直到我离开
TabbedFragment
并返回

我创建如下选项卡:

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

        final ActionBar actionBar = getActionBar();

        tabs = Lists.newArrayList();
        tabs.add(new TabDefinition<>("Tab 1"));
        tabs.add(new TabDefinition<>("Tab 2"));
        tabs.add(new TabDefinition<>("Tab 3"));
        tabs.add(new TabDefinition<>("Tab 4"));


        for (TabDefinition tab : tabs) {
            actionBar.addTab(actionBar.newTab()
                .setText(tab.text)
                .setTag(tab.tag)
                .setTabListener(this));
        }
    }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.paging_tab_container, container, false);
}

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

    viewPager.setAdapter(new FragmentStatePagerAdapter(getFragmentManager()) {

        @Override
        public Fragment getItem(int position) {
            return tabs.get(position).fragment;
        }

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

    viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            getActionBar().setSelectedNavigationItem(position);
        }
    });

    viewPager.setCurrentItem(getActionBar().getSelectedNavigationIndex(), true);
}
返回到
TabbedFragment
所选选项卡时,其旁边的1将不包含任何内容。只是空视图。但如果我选择当前+2,则加载片段内容。然后返回到第一个片段,重新加载内容。
例如,我有A、B、C、D选项卡。离开
TabbedFragment
之前,我选择了选项卡A。 当返回到
TabbedFragment
时,我仍然在选项卡A,但它是空的。选项卡B也是如此。
但当选择tab C时,会创建并加载它。返回到选项卡A,它将被重新创建


这里可能有什么问题?

我认为问题存在于用作选项卡的片段中。恢复时,它们似乎没有显示任何内容(请参阅)。“奇怪”的问题是,只有当前选择的+/-1选项卡是空的,这是因为默认情况下,
ViewPager的属性为1。所有高于此阈值的选项卡都将重新创建


因此,在您的情况下,增加该值将导致恢复后所有选项卡都显示为空。请检查片段代码,您使用哪些生命周期方法来膨胀布局、设置适配器等等,因为这就是导致您出现问题的原因。

我猜发生这种情况的原因是,在加载片段时,android加载current和current+1,如果您进行调试,您将不会看到onPause被调用以获取下一个片段


您可以在TabHost.OnTabChangeListener的onTabChanged()方法中以编程方式重新加载内容。

好的,因此当使用
FragmentStatePagerAdapter
时,当您导航到一个以上的片段时,您的片段将被销毁,因为默认情况下,
offScreenPageLimit
默认设置为1,如上所述

通常,此类用于包含大量
片段的活动,即必须在大量视图中滚动。如果您的应用程序只需要3-4个选项卡,我建议使用
FragmentPagerAdapter
,然后将offScreenPageLimit指定为3,因此如果您使用第4个选项卡,之前的所有3个选项卡仍将保留在内存中

下面是我在github上创建的一个项目的一些示例代码,说明了如果不想添加这个offScreenPageLimit,如何动态加载片段

在这个类中浏览所有这些代码,您将看到每次滑动我的
ViewPager
时,我是如何动态加载片段的。最明显的是在底部

您可以下载此代码,并将其用作您想要执行的操作的测试基础。 尝试在viewPager的onCreate()方法中添加setOffScreenPageLimit(2),并注意不同的行为。要检查行为,请编辑片段1中的文本。无论是否使用此集合,都可以导航到其他位置并返回。您将看到,当它被设置时,片段的文本仍然是您将其更改为的文本,因为片段永远不会被重新创建

如果您有其他问题,请提供

祝你好运

更新

private static final String [] fragmentClasses = {"com.example.project.YourFragment1","com.example.project.YourFragment2","com.example.project.YourFragment3"};



 viewPager.setAdapter(new FragmentStatePagerAdapter(getFragmentManager()) {

    @Override
    public Fragment getItem(int position) {

       Fragment fragmentAtPosition = null;

       // $$$$ This is the Important Part $$$$$
       // Check to make sure that your array is not null, size is greater than 0 , current position is greater than equal to 0, and position is less than length
       if((fragmentClasses != null) && (fragmentClasses.length > 0)&&(position >= 0)&& (position < fragmentClasses.length))
        {
       // Instantiate the Fragment at the current position of the Adapter
        fragmentAtPosition = Fragment.instantiate(getBaseContext(), fragmentClasses[position]);
        fragmentAtPosition.setRetainInstance(true);

       }

        return fragmentAtPosition;
    }

    @Override
    public int getCount() {
        return fragmentClasses.length;
    }
});
private static final String[]fragmentClasses={“com.example.project.yourframent1”、“com.example.project.yourframent2”、“com.example.project.yourframent3”};
viewPager.setAdapter(新的FragmentStatePagerAdapter(getFragmentManager()){
@凌驾
公共片段getItem(int位置){
片段fragmentAtPosition=null;
//$$$$这是重要的部分$$$$$
//检查以确保数组不为null,大小大于0,当前位置大于等于0,位置小于长度
if((fragmentClasses!=null)&&(fragmentClasses.length>0)&&(position>=0)&(position
过了一会儿,又遇到了同样的问题,所以更新这个问题。
如果您使用的是
FragmentStatePagerAdapter
您应该通过
getChildFragmentManager()
而不是
getFragmentManager()
提供
FragmentManager
。看

在做了大量研究之后,这对我来说很有效。 我有一个复杂的布局,一个片段中有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;
}

或者更简单地说,当导航回
选项卡片段
(假设您使用了一个意图并且片段在活动中)时,使用:


这将保留原始活动并将其移动到堆栈顶部,而不是重新创建它,因此您永远不需要重新创建viewPager。

您的片段中有viewPager,现在选项卡的用途是什么?你能提供实际的结构吗?这就是全部。你还需要什么?好的,很快的问题。你有一个viewpager在一个带有viewpager的活动的片段中?是的,活动有一个带有viewpager的片段,它显示片段。你是如何解决的?是的
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);