summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2015-05-07 16:56:42 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-05-07 16:56:43 +0000
commit1bc3c849ba5e9f23dd7e93012c4b5800b78c221b (patch)
tree4648e116daec2b2dde812ecb99734fd603c09876
parentdd441795409f26f45de3ce40a1bab4121cfcefe5 (diff)
parent0698594d478926ab4694ac0f8429847bad2ceedb (diff)
Merge "Fix leak in LayoutTransition" into mnc-dev
-rw-r--r--core/java/android/animation/LayoutTransition.java67
1 files changed, 51 insertions, 16 deletions
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index 57906824caa1..cdd72be76805 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -28,6 +28,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
/**
* This class enables automatic animations on layout changes in ViewGroup objects. To enable
@@ -757,7 +758,7 @@ public class LayoutTransition {
// reset the inter-animation delay, in case we use it later
staggerDelay = 0;
- final ViewTreeObserver observer = parent.getViewTreeObserver(); // used for later cleanup
+ final ViewTreeObserver observer = parent.getViewTreeObserver();
if (!observer.isAlive()) {
// If the observer's not in a good state, skip the transition
return;
@@ -790,21 +791,9 @@ public class LayoutTransition {
// This is the cleanup step. When we get this rendering event, we know that all of
// the appropriate animations have been set up and run. Now we can clear out the
// layout listeners.
- observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
- public boolean onPreDraw() {
- parent.getViewTreeObserver().removeOnPreDrawListener(this);
- int count = layoutChangeListenerMap.size();
- if (count > 0) {
- Collection<View> views = layoutChangeListenerMap.keySet();
- for (View view : views) {
- View.OnLayoutChangeListener listener = layoutChangeListenerMap.get(view);
- view.removeOnLayoutChangeListener(listener);
- }
- }
- layoutChangeListenerMap.clear();
- return true;
- }
- });
+ CleanupCallback callback = new CleanupCallback(layoutChangeListenerMap, parent);
+ observer.addOnPreDrawListener(callback);
+ parent.addOnAttachStateChangeListener(callback);
}
/**
@@ -1499,4 +1488,50 @@ public class LayoutTransition {
View view, int transitionType);
}
+ /**
+ * Utility class to clean up listeners after animations are setup. Cleanup happens
+ * when either the OnPreDrawListener method is called or when the parent is detached,
+ * whichever comes first.
+ */
+ private static final class CleanupCallback implements ViewTreeObserver.OnPreDrawListener,
+ View.OnAttachStateChangeListener {
+
+ final Map<View, View.OnLayoutChangeListener> layoutChangeListenerMap;
+ final ViewGroup parent;
+
+ CleanupCallback(Map<View, View.OnLayoutChangeListener> listenerMap, ViewGroup parent) {
+ this.layoutChangeListenerMap = listenerMap;
+ this.parent = parent;
+ }
+
+ private void cleanup() {
+ parent.getViewTreeObserver().removeOnPreDrawListener(this);
+ parent.removeOnAttachStateChangeListener(this);
+ int count = layoutChangeListenerMap.size();
+ if (count > 0) {
+ Collection<View> views = layoutChangeListenerMap.keySet();
+ for (View view : views) {
+ View.OnLayoutChangeListener listener = layoutChangeListenerMap.get(view);
+ view.removeOnLayoutChangeListener(listener);
+ }
+ layoutChangeListenerMap.clear();
+ }
+ }
+
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ cleanup();
+ }
+
+ @Override
+ public boolean onPreDraw() {
+ cleanup();
+ return true;
+ }
+ };
+
}