diff options
| author | 2013-09-13 13:29:31 -0700 | |
|---|---|---|
| committer | 2013-09-14 12:06:18 -0700 | |
| commit | 7660d121b2ef21164ed33e6091e5dd50f5d0f939 (patch) | |
| tree | cb1046fb4edb97d80f0c23b2621bd0dbbed0f5eb | |
| parent | 78d0cf7958dfde7951ed1a2c0317e04d6b41f4f3 (diff) | |
Plug leaks in transitions
Transitions were leaking views due to TransitionsValues holding references
to views/parents. The references were fine, but the retention of the transition
objects themselves were not. There were a few different places that needed to
be plugged:
- clones were not making new copies of some fields, leading to caching references
in the original object (which was then cloned later to other clones)
- Visibility was using a persistent field to cache temporary values. This transition,
when cloned, would retain these instances, keeping references to views
- ViewTreeObserver had a bug that would leak listeners
Issue #10749071 Activity instance leak between TransitionManager and InputMethodManager
Change-Id: I1d5d457dc5e020c7b9e8392a95e3b2c488461119
| -rw-r--r-- | core/java/android/transition/Transition.java | 2 | ||||
| -rw-r--r-- | core/java/android/transition/TransitionManager.java | 29 | ||||
| -rw-r--r-- | core/java/android/transition/Visibility.java | 5 | ||||
| -rw-r--r-- | core/java/android/view/ViewTreeObserver.java | 2 |
4 files changed, 23 insertions, 15 deletions
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java index c588c6bf4c7a..2fb32aafad0c 100644 --- a/core/java/android/transition/Transition.java +++ b/core/java/android/transition/Transition.java @@ -1451,6 +1451,8 @@ public abstract class Transition implements Cloneable { try { clone = (Transition) super.clone(); clone.mAnimators = new ArrayList<Animator>(); + clone.mStartValues = new TransitionValuesMaps(); + clone.mEndValues = new TransitionValuesMaps(); } catch (CloneNotSupportedException e) {} return clone; diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java index 54d801eba443..727a98dceb9a 100644 --- a/core/java/android/transition/TransitionManager.java +++ b/core/java/android/transition/TransitionManager.java @@ -22,6 +22,7 @@ import android.util.Log; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import java.lang.ref.WeakReference; import java.util.ArrayList; /** @@ -68,8 +69,9 @@ public class TransitionManager { ArrayMap<Scene, Transition> mSceneTransitions = new ArrayMap<Scene, Transition>(); ArrayMap<Scene, ArrayMap<Scene, Transition>> mScenePairTransitions = new ArrayMap<Scene, ArrayMap<Scene, Transition>>(); - private static ThreadLocal<ArrayMap<ViewGroup, ArrayList<Transition>>> sRunningTransitions = - new ThreadLocal<ArrayMap<ViewGroup, ArrayList<Transition>>>(); + private static ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>> + sRunningTransitions = + new ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>(); private static ArrayList<ViewGroup> sPendingTransitions = new ArrayList<ViewGroup>(); @@ -184,20 +186,24 @@ public class TransitionManager { } private static ArrayMap<ViewGroup, ArrayList<Transition>> getRunningTransitions() { - ArrayMap<ViewGroup, ArrayList<Transition>> runningTransitions = + WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>> runningTransitions = sRunningTransitions.get(); - if (runningTransitions == null) { - runningTransitions = new ArrayMap<ViewGroup, ArrayList<Transition>>(); + if (runningTransitions == null || runningTransitions.get() == null) { + ArrayMap<ViewGroup, ArrayList<Transition>> transitions = + new ArrayMap<ViewGroup, ArrayList<Transition>>(); + runningTransitions = new WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>( + transitions); sRunningTransitions.set(runningTransitions); } - return runningTransitions; + return runningTransitions.get(); } private static void sceneChangeRunTransition(final ViewGroup sceneRoot, final Transition transition) { if (transition != null) { final ViewTreeObserver observer = sceneRoot.getViewTreeObserver(); - observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + final ViewTreeObserver.OnPreDrawListener listener = + new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this); sPendingTransitions.remove(sceneRoot); @@ -236,7 +242,8 @@ public class TransitionManager { // values set on them again and avoid artifacts. return false; } - }); + }; + observer.addOnPreDrawListener(listener); } } @@ -355,10 +362,10 @@ public class TransitionManager { // if (transition == null) { // transition = sDefaultTransition; // } -// final Transition finalTransition = transition.clone(); -// sceneChangeSetup(sceneRoot, transition); +// final Transition transitionClone = transition.clone(); +// sceneChangeSetup(sceneRoot, transitionClone); // Scene.setCurrentScene(sceneRoot, null); -// sceneChangeRunTransition(sceneRoot, finalTransition); +// sceneChangeRunTransition(sceneRoot, transitionClone); // } } } diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index 75d3e7c0b4e0..f49821fab1c3 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -65,9 +65,6 @@ public abstract class Visibility extends Transition { ViewGroup endParent; } - // Temporary structure, used in calculating state in setup() and play() - private VisibilityInfo mTmpVisibilityInfo = new VisibilityInfo(); - @Override public String[] getTransitionProperties() { return sTransitionProperties; @@ -161,7 +158,7 @@ public abstract class Visibility extends Transition { private VisibilityInfo getVisibilityChangeInfo(TransitionValues startValues, TransitionValues endValues) { - final VisibilityInfo visInfo = mTmpVisibilityInfo; + final VisibilityInfo visInfo = new VisibilityInfo(); visInfo.visibilityChange = false; visInfo.fadeIn = false; if (startValues != null) { diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java index 730c4eb01cd0..ad8b51db4a1a 100644 --- a/core/java/android/view/ViewTreeObserver.java +++ b/core/java/android/view/ViewTreeObserver.java @@ -992,6 +992,8 @@ public final class ViewTreeObserver { mData = mDataCopy; } mDataCopy = null; + mAccess.mData.clear(); + mAccess.mSize = 0; } int size() { |