【发布时间】:2015-05-19 02:59:28
【问题描述】:
所以基本上我的工作与 Instagram 应用程序非常相似,其中有许多选项卡,用户可以毫无延迟地切换到任何选项卡,无论发生什么事情,例如刷新、重新加载、等等。它还使用后退按钮返回上一个保留的选项卡。
为了实现这一点,我使用FragmentManager 和FragmentTransaction 来显示和隐藏代表每个选项卡的每个片段。我没有使用replace 或attach / detach,因为它们破坏了前一个选项卡的视图层次结构。
我的实现工作得很好,只是没有提交显示和隐藏片段(我非常怀疑这是一个正确的词,但到目前为止我是这样理解流程的。),或者不会立即发生 当SwipeRefreshLayout 刷新片段(被隐藏)时,该片段被添加到FragmentManager,比要显示的片段晚。
我的实现遵循这些规则。假设我们有 4 个选项卡,我的 MainActivity 显示第一个选项卡,例如 FirstFragment,而用户选择第二个选项卡 SecondFragment。因为以前从未添加过 SecondFragment,所以我使用 FragmentTransaction.add 将其添加到 FragmentManager 并使用 FragmentTransaction.hide 隐藏 FirstFragment。如果用户再次选择第一个选项卡,因为 FirstFragment 之前已添加到 FragmentManager,它不会添加而只显示 FirstFragment 并隐藏 SecondFragment。在这两个选项卡之间进行选择很顺利。
但是当用户“刷新”SecondFragment 的SwipeRefreshLayout 并选择第一个选项卡时,FragmentTransaction 等待 SecondFragment 的刷新完成并提交(?) 实际交易。奇怪的是事务是立即提交的,从 FirstFragment 的刷新到 SecondFragment。
因为这是按添加到FragmentManager 的顺序发生的,所以我怀疑添加顺序会以某种方式影响片段的回栈,并且可能存在诸如 UI 线程优先级之类的东西,因此它会强制片段事务在以后发生-添加片段的 UI 过渡完成。但我只是没有足够的线索来解决这个问题。我已经尝试在FragmentTransaction 上附加/分离和返回堆栈,但无法解决问题。 FragmentTransaction.commit 和 FragmentTransaction.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();
}
}
【问题讨论】:
-
您是否尝试过调用 executePendingTransactions()?试试看是否有帮助。
-
@dora 我在提交语句之后添加了
executePendingTransactions(),但它不起作用。我想知道这是否是一个正确的地方,因为文件所说的似乎是我的情况的答案。
标签: android android-fragments tabs instagram fragmentmanager