Skip to content

Commit 1a76dcd

Browse files
committed
Fix issue #5367164: memory leak in LayoutTransition
When a transition occurs, layout change listeners are added to the container being transitioned as well as every container up the view hierarchy. The parent views were not having those listeners removed, so every time a transition ran, more listeners would be added. Adding to that, the use of an ArrayList as the collection to hold the listeners meant that adding duplicate items would just increase the size of the list. There's now a sanity-check on the add call to make sure that the listener does not exist already, but more importantly we remove all listeners added when the transition ends. Change-Id: I4ea05adf30765db091124065539b0ffd32729b3b
1 parent 11a6705 commit 1a76dcd

File tree

2 files changed

+11
-5
lines changed

2 files changed

+11
-5
lines changed

core/java/android/animation/LayoutTransition.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import android.view.animation.DecelerateInterpolator;
2525

2626
import java.util.ArrayList;
27+
import java.util.Collection;
2728
import java.util.HashMap;
2829
import java.util.LinkedHashMap;
2930
import java.util.List;
@@ -615,10 +616,13 @@ private void runChangeTransition(final ViewGroup parent, View newView, final int
615616
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
616617
public boolean onPreDraw() {
617618
parent.getViewTreeObserver().removeOnPreDrawListener(this);
618-
int numChildren = parent.getChildCount();
619-
for (int i = 0; i < numChildren; ++i) {
620-
final View child = parent.getChildAt(i);
621-
child.removeOnLayoutChangeListener(layoutChangeListenerMap.get(child));
619+
int count = layoutChangeListenerMap.size();
620+
if (count > 0) {
621+
Collection<View> views = layoutChangeListenerMap.keySet();
622+
for (View view : views) {
623+
View.OnLayoutChangeListener listener = layoutChangeListenerMap.get(view);
624+
view.removeOnLayoutChangeListener(listener);
625+
}
622626
}
623627
layoutChangeListenerMap.clear();
624628
return true;

core/java/android/view/View.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3335,7 +3335,9 @@ public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
33353335
if (mOnLayoutChangeListeners == null) {
33363336
mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
33373337
}
3338-
mOnLayoutChangeListeners.add(listener);
3338+
if (!mOnLayoutChangeListeners.contains(listener)) {
3339+
mOnLayoutChangeListeners.add(listener);
3340+
}
33393341
}
33403342

33413343
/**

0 commit comments

Comments
 (0)