刷新 SwipeRefreshLayout 时,不会立即提交(不会发生)显示和隐藏片段

Showing and hiding fragments are not committed (don't occur) immediately when SwipeRefreshLayout is refreshing

所以基本上我正在做的工作与 Instagram 应用程序非常相似,其中有许多选项卡,用户可以毫不延迟地切换到任何选项卡,无论发生什么事情,例如刷新,重新加载等。它还使用后退按钮返回到上一个保留的选项卡。

为了实现这一点,我使用 FragmentManagerFragmentTransaction 来显示和隐藏代表每个选项卡的每个片段。我没有使用 replaceattach / detach 因为它们会破坏上一个选项卡的视图层次结构。

我的实现工作得很好,除了显示和隐藏片段没有提交(我非常怀疑这是一个正确的词,但到目前为止我是这样理解流程的。),或者不立即发生 SwipeRefreshLayout 刷新添加到 FragmentManager 的片段(要隐藏)时,该片段晚于要显示的片段

我的实现遵循这些规则。假设我们有 4 个选项卡,我的 MainActivity 显示第一个选项卡,比如 FirstFragment,用户选择第二个选项卡,第二个片段。因为以前从未添加过 SecondFragment,所以我使用 FragmentTransaction.add 将其添加到 FragmentManager 并使用 [=隐藏 FirstFragment FragmentTransaction.hide。如果用户再次选择第一个选项卡,因为 FirstFragment 之前已添加到 FragmentManager,它不会添加,只会显示 FirstFragment并隐藏 SecondFragment。在这两个选项卡之间进行选择可以顺利进行。

但是当用户 "refreshes" SecondFragmentSwipeRefreshLayout 并选择第一个选项卡时,FragmentTransaction 等待 SecondFragment 的刷新将完成并提交(?)实际事务。奇怪的是,从FirstFragment的刷新到SecondFragment.

,事务是立即提交的

因为这是按添加到 FragmentManager 的顺序发生的,我怀疑添加顺序会以某种方式影响片段的回栈,并且可能存在类似 UI 线程优先级的东西,因此它强制片段事务将在稍后添加的片段的 UI 转换完成后发生。但我只是没有足够的线索来解决这个问题。我已经尝试在 FragmentTransaction 上附加/分离和回退,但无法解决问题。 FragmentTransaction.commitFragmentTransaction.commitAllowingStateLoss 我都试过了,但都没有解决问题。

这些是我的 MainActivity 的示例代码。

private ArrayList<Integer> mFragmentsStack; // This is simple psuedo-stack which only stores
                                            // the order of fragments stack to collaborate
                                            // when back button is pressed.
private ArrayList<Fragment> mFragmentsList;

@Override
protected void onCreate() {
    mFragmentsStack = new ArrayList<>();
    mFragmentsList = new ArrayList<>();
    mFragmentsList.add(FirstFragment.newInstance());
    mFragmentsList.add(SecondFragment.newInstance());
    mFragmentsList.add(ThirdFragment.newInstance());
    mFragmentsList.add(FourthFragment.newInstance());
    mMainTab = (MainTab) findViewById(R.id.main_tab);
    mMainTab.setOnMainTabClickListener(this);

    int currentTab = DEFAULT_TAB;

    mFragmentsStack.add(currentTab);
    getSupportFragmentManager().beginTransaction().add(R.id.main_frame_layout,
            mFragmentsList.get(currentTab), String.valueOf(currentTab)).commit();
    mMainTab.setCurrentTab(currentTab);
}

// This is custom interface.
@Override
public void onTabClick(int oldPosition, int newPosition) {
    if (oldPosition != newPosition) {
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();

        // First hide the old tab.
        fragmentTransaction.hide(mFragmentsList.get(oldPosition));

        // Recalculate the fragment stack.
        if (mFragmentsStack.contains(newPosition)) {
            mFragmentsStack.remove((Integer) newPosition);
        }
        mFragmentsStack.add(newPosition);

        // Add new fragment if it's not added before, or show new fragment which was already hidden.
        Fragment fragment = getSupportFragmentManager().findFragmentByTag(String.valueOf(newPosition));
        if (fragment != null) {
            fragmentTransaction.show(fragment);
        } else {
            fragmentTransaction.add(R.id.main_frame_layout, mFragmentsList.get(newPosition),
                    String.valueOf(newPosition));
        }

        // Commit the transaction.
        fragmentTransaction.commitAllowingStateLoss();
    }
}

// It mimics the tab behavior of Instagram Android application.
@Override
public void onBackPressed() {
    // If there's only one fragment on stack, super.onBackPressed.
    // If it's not, then hide the current fragment and show the previous fragment.
    int lastIndexOfFragmentsStack = mFragmentsStack.size() - 1;
    if (lastIndexOfFragmentsStack - 1 >= 0) {
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.hide(mFragmentsList.get(mFragmentsStack.get(lastIndexOfFragmentsStack)));
        fragmentTransaction.show(mFragmentsList.get(mFragmentsStack.get(lastIndexOfFragmentsStack - 1)));
        fragmentTransaction.commitAllowingStateLoss();
        mMainTab.setCurrentTab(mFragmentsStack.get(lastIndexOfFragmentsStack - 1));
        mFragmentsStack.remove(lastIndexOfFragmentsStack);
    } else {
        super.onBackPressed();
    }
}

刚遇到同样的问题,唯一不同的是 - 我在点击工具栏按钮时切换片段。 我设法摆脱了覆盖 onHiddenChanged 的​​重叠片段:

@Override
public void onHiddenChanged(boolean hidden) {
    super.onHiddenChanged(hidden);
    if (hidden) {
        yourSwipeRefreshLayout.setRefreshing(false);
    }
}