0

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

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

  1. 用户在当前包含片段 A 的页面上按下按钮
  2. 片段 A 被替换为一些新的片段 B
  3. 用户在片段 B 中做一些工作,然后在他/她完成后按下按钮
  4. 片段 B 被移除,并被片段 A(原始片段)替换

我找到了一种方法来做到这一点,但它似乎有很大的缺陷。该解决方案涉及删除原始片段,然后覆盖getItemPosition(基本上是此相关问题中描述的方法):

//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 个主要片段的引用,并将它们换入和换出页面,而不必每次都重新创建它们。有任何想法吗?

4

2 回答 2

1

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

在您的情况下,不是一直调用 Fragment.newInstance() ,而是在创建新的之前检查保留器对象中包含的片段是否为空。如果它不为空,只需重新使用前一个实例。这种检查应该发生在您的 ViewPager 适配器的 getItem(int) 方法中。

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

于 2012-09-26T22:00:54.487 回答
1

FragmentPagerAdapter 提供了一个可覆盖的方法getItemId,该方法将在此处为您提供帮助。

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

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

于 2013-10-22T22:35:54.813 回答