使用FragmentPagerAdapter替换ViewPager中的片段

时间:2012-04-04 06:05:00

标签: android android-fragments android-viewpager

我正在使用一个包含4页的ViewPager,我正在寻找一种有效的方法来替换/切换每页中的片段。

这是我正在尝试创建的交互模式:

  1. 用户按下当前包含片段A的页面上的按钮
  2. 片段A被替换为一些新的片段B
  3. 用户在片段B中完成一些工作,然后在完成后按下按钮
  4. 去除片段B,并用片段A(原始片段)替换
  5. 我找到了一种方法,但它似乎有很大的缺陷。解决方案包括删除原始片段,然后覆盖getItemPosition(基本上是此related question中描述的方法):

    //An array to keep track of the currently visible fragment in each page
    private final Fragment[] activeFragments= new Fragment[4];
    
    public void openFragmentB(ViewPager pager, int position) {
    
        startUpdate(pager);
    
        //Remove the original fragment
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.remove(activeFragments[position]);
        transaction.commit();
    
        //Create a new tile search fragment to replace the original fragment
        activeFragments[position] = FragmentB.newInstance();
        pageStates[position] = PageState.STATE_B;
    
        finishUpdate(pager);
        notifyDataSetChanged();
    }
    
    @Override
    public int getItemPosition(Object object) {
    
        //If the main fragment is not active, return POSITION_NONE
        if(object instanceof FragmentA) {
            FragmentA a = (FragmentA) object;
            if(pageStates[a.getPosition()] != PageState.STATE_A) {
                return POSITION_NONE;
            }
        }
    
        //If the secondary fragment is not active, return POSITION_NONE
        if(object instanceof FragmentB) {
            FragmentB b = (FragmentB) object;
            if(pageStates[b.getPosition()] != PageState.STATE_B) {
                return POSITION_NONE;
            }
        }
    
        return POSITION_UNCHANGED;
    }
    

    此方法有效,但有不良副作用。删除片段并将其位置设置为POSITION_NONE会导致片段被破坏。因此,当用户完成使用FragmentB时,我需要创建一个新的FragmentA实例,而不是重用原始片段。寻呼机中的主要片段(本例中为FragmentA)将包含相对较大的数据库备份列表,因此我希望尽可能避免重新创建它们。

    基本上我只想保留对我的4个主要片段的引用,并将它们交换进页面,而不必每次都重新创建它们。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

避免重新创建Fragments的一种简单方法是将它们作为成员变量保存在Activity中。无论如何,我与onRetainCustomNonConfigurationInstance()一起执行此操作,以便在配置更改期间保留我的片段(主要是屏幕旋转)。我将Fragments保存在'retainer'对象中,因为onRetainCustomNonConfigurationInstance只返回一个对象。

在您的情况下,不是一直调用Fragment.newInstance(),而是在创建新对象之前检查包含在retaininer对象中的片段是否为null。如果它不为null,则只需重新使用上一个实例。此检查应在ViewPager适配器的getItem(int)方法中进行。

实际上,这样做基本上意味着您正在处理调用getItem时是否回收Fragment,并覆盖getItemPosition(Object)方法,以便在相关Segments时始终返回POSITION_NONE。

答案 1 :(得分:1)

FragmentPagerAdapter提供了一个名为getItemId的可覆盖方法,可以在这里为您提供帮助。

如果为集合中的每个Fragment分配一个唯一的long值,并在此方法中返回该值,则会在注意到id已更改时强制ViewPager重新加载页面。

迟到总比没有好,我希望这有助于那里的人!