diff options
| author | 2015-11-30 10:32:47 -0800 | |
|---|---|---|
| committer | 2015-11-30 10:58:37 -0800 | |
| commit | fbaa14bc35e8d7366596053cac8a445084bac44c (patch) | |
| tree | 04f8201325fd97f54f4439354d11c2a517190c75 | |
| parent | 2b2d23aa706c2d8efb05e15f08bdc41883a4a651 (diff) | |
Choose the correct Fragment to pull a Transiton from.
Bug 25375640
When popping multiple back stacks or replacing multiple times
within a transaction, the wrong fragment could have been
chosen. This normally occured when one of the Fragments had
a null Transition.
Change-Id: Ic2c842d9228ee7d26bf067016cb3f307bdf92991
| -rw-r--r-- | core/java/android/app/BackStackRecord.java | 61 |
1 files changed, 37 insertions, 24 deletions
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java index 754a5710191b..b24bce3107d1 100644 --- a/core/java/android/app/BackStackRecord.java +++ b/core/java/android/app/BackStackRecord.java @@ -798,21 +798,33 @@ final class BackStackRecord extends FragmentTransaction implements } } - private static void setFirstOut(SparseArray<Fragment> fragments, Fragment fragment) { + private static void setFirstOut(SparseArray<Fragment> firstOutFragments, + SparseArray<Fragment> lastInFragments, Fragment fragment) { if (fragment != null) { int containerId = fragment.mContainerId; - if (containerId != 0 && !fragment.isHidden() && fragment.isAdded() && - fragment.getView() != null && fragments.get(containerId) == null) { - fragments.put(containerId, fragment); + if (containerId != 0 && !fragment.isHidden()) { + if (fragment.isAdded() && fragment.getView() != null + && firstOutFragments.get(containerId) == null) { + firstOutFragments.put(containerId, fragment); + } + if (lastInFragments.get(containerId) == fragment) { + lastInFragments.remove(containerId); + } } } } - private void setLastIn(SparseArray<Fragment> fragments, Fragment fragment) { + private void setLastIn(SparseArray<Fragment> firstOutFragments, + SparseArray<Fragment> lastInFragments, Fragment fragment) { if (fragment != null) { int containerId = fragment.mContainerId; if (containerId != 0) { - fragments.put(containerId, fragment); + if (!fragment.isAdded()) { + lastInFragments.put(containerId, fragment); + } + if (firstOutFragments.get(containerId) == fragment) { + firstOutFragments.remove(containerId); + } } } } @@ -835,7 +847,7 @@ final class BackStackRecord extends FragmentTransaction implements while (op != null) { switch (op.cmd) { case OP_ADD: - setLastIn(lastInFragments, op.fragment); + setLastIn(firstOutFragments, lastInFragments, op.fragment); break; case OP_REPLACE: { Fragment f = op.fragment; @@ -845,29 +857,30 @@ final class BackStackRecord extends FragmentTransaction implements if (f == null || old.mContainerId == f.mContainerId) { if (old == f) { f = null; + lastInFragments.remove(old.mContainerId); } else { - setFirstOut(firstOutFragments, old); + setFirstOut(firstOutFragments, lastInFragments, old); } } } } - setLastIn(lastInFragments, f); + setLastIn(firstOutFragments, lastInFragments, op.fragment); break; } case OP_REMOVE: - setFirstOut(firstOutFragments, op.fragment); + setFirstOut(firstOutFragments, lastInFragments, op.fragment); break; case OP_HIDE: - setFirstOut(firstOutFragments, op.fragment); + setFirstOut(firstOutFragments, lastInFragments, op.fragment); break; case OP_SHOW: - setLastIn(lastInFragments, op.fragment); + setLastIn(firstOutFragments, lastInFragments, op.fragment); break; case OP_DETACH: - setFirstOut(firstOutFragments, op.fragment); + setFirstOut(firstOutFragments, lastInFragments, op.fragment); break; case OP_ATTACH: - setLastIn(lastInFragments, op.fragment); + setLastIn(firstOutFragments, lastInFragments, op.fragment); break; } @@ -889,38 +902,38 @@ final class BackStackRecord extends FragmentTransaction implements if (!mManager.mContainer.onHasView()) { return; // nothing to see, so no transitions } - Op op = mHead; + Op op = mTail; while (op != null) { switch (op.cmd) { case OP_ADD: - setFirstOut(firstOutFragments, op.fragment); + setFirstOut(firstOutFragments, lastInFragments, op.fragment); break; case OP_REPLACE: if (op.removed != null) { for (int i = op.removed.size() - 1; i >= 0; i--) { - setLastIn(lastInFragments, op.removed.get(i)); + setLastIn(firstOutFragments, lastInFragments, op.removed.get(i)); } } - setFirstOut(firstOutFragments, op.fragment); + setFirstOut(firstOutFragments, lastInFragments, op.fragment); break; case OP_REMOVE: - setLastIn(lastInFragments, op.fragment); + setLastIn(firstOutFragments, lastInFragments, op.fragment); break; case OP_HIDE: - setLastIn(lastInFragments, op.fragment); + setLastIn(firstOutFragments, lastInFragments, op.fragment); break; case OP_SHOW: - setFirstOut(firstOutFragments, op.fragment); + setFirstOut(firstOutFragments, lastInFragments, op.fragment); break; case OP_DETACH: - setLastIn(lastInFragments, op.fragment); + setLastIn(firstOutFragments, lastInFragments, op.fragment); break; case OP_ATTACH: - setFirstOut(firstOutFragments, op.fragment); + setFirstOut(firstOutFragments, lastInFragments, op.fragment); break; } - op = op.next; + op = op.prev; } } |