Properly track fragments from pop operations.
am: e7e8d3d3a5
Change-Id: Ibffe0f20f43db35f0e0d273d1c78a01040ef71d1
diff --git a/fragment/java/android/support/v4/app/BackStackRecord.java b/fragment/java/android/support/v4/app/BackStackRecord.java
index acfa924..3b41d60 100644
--- a/fragment/java/android/support/v4/app/BackStackRecord.java
+++ b/fragment/java/android/support/v4/app/BackStackRecord.java
@@ -795,7 +795,7 @@
default:
throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
}
- if (!mAllowOptimization && op.cmd != OP_ADD) {
+ if (!mAllowOptimization && op.cmd != OP_REMOVE) {
mManager.moveFragmentToExpectedState(f);
}
}
@@ -861,6 +861,29 @@
}
}
+ /**
+ * Removes fragments that are added or removed during a pop operation.
+ *
+ * @param added Initialized to the fragments that are in the mManager.mAdded, this
+ * will be modified to contain the fragments that will be in mAdded
+ * after the execution ({@link #executeOps()}.
+ */
+ void trackAddedFragmentsInPop(ArrayList<Fragment> added) {
+ for (int opNum = 0; opNum < mOps.size(); opNum++) {
+ final Op op = mOps.get(opNum);
+ switch (op.cmd) {
+ case OP_ADD:
+ case OP_ATTACH:
+ added.remove(op.fragment);
+ break;
+ case OP_REMOVE:
+ case OP_DETACH:
+ added.add(op.fragment);
+ break;
+ }
+ }
+ }
+
boolean isPostponed() {
for (int opNum = 0; opNum < mOps.size(); opNum++) {
final Op op = mOps.get(opNum);
diff --git a/fragment/java/android/support/v4/app/FragmentManager.java b/fragment/java/android/support/v4/app/FragmentManager.java
index b10170a..bf1c371 100644
--- a/fragment/java/android/support/v4/app/FragmentManager.java
+++ b/fragment/java/android/support/v4/app/FragmentManager.java
@@ -2128,6 +2128,8 @@
final boolean isPop = isRecordPop.get(recordNum);
if (!isPop) {
record.expandReplaceOps(mTmpAddedFragments);
+ } else {
+ record.trackAddedFragmentsInPop(mTmpAddedFragments);
}
final int bumpAmount = isPop ? -1 : 1;
record.bumpBackStackNesting(bumpAmount);
diff --git a/fragment/tests/java/android/support/v4/app/FragmentViewTests.java b/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
index ad970c8..98c9d40 100644
--- a/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
+++ b/fragment/tests/java/android/support/v4/app/FragmentViewTests.java
@@ -902,6 +902,43 @@
assertEquals(View.GONE, fragment2.getView().getVisibility());
}
+ // Test to ensure that popping and adding a fragment properly track the fragments added
+ // and removed.
+ @Test
+ public void popAdd() throws Throwable {
+ FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
+ ViewGroup container = (ViewGroup)
+ mActivityRule.getActivity().findViewById(R.id.fragmentContainer);
+ final FragmentManager fm = mActivityRule.getActivity().getSupportFragmentManager();
+
+ // One fragment with a view
+ final StrictViewFragment fragment1 = new StrictViewFragment();
+ fm.beginTransaction().add(R.id.fragmentContainer, fragment1).addToBackStack(null).commit();
+ FragmentTestUtil.executePendingTransactions(mActivityRule);
+ FragmentTestUtil.assertChildren(container, fragment1);
+
+ final StrictViewFragment fragment2 = new StrictViewFragment();
+ final StrictViewFragment fragment3 = new StrictViewFragment();
+ mInstrumentation.runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ fm.popBackStack();
+ fm.beginTransaction()
+ .replace(R.id.fragmentContainer, fragment2)
+ .addToBackStack(null)
+ .commit();
+ fm.executePendingTransactions();
+ fm.popBackStack();
+ fm.beginTransaction()
+ .replace(R.id.fragmentContainer, fragment3)
+ .addToBackStack(null)
+ .commit();
+ fm.executePendingTransactions();
+ }
+ });
+ FragmentTestUtil.assertChildren(container, fragment3);
+ }
+
private View findViewById(int viewId) {
return mActivityRule.getActivity().findViewById(viewId);
}