summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorPatrick Dubroy <dubroy@google.com>2011-01-13 17:55:37 -0800
committerPatrick Dubroy <dubroy@google.com>2011-01-14 14:13:31 -0800
commitec84c3a189e4aa70aa6ea8ba712e5a4f260a153b (patch)
treebe5f82da1bec89ee491154bbc001bc8523e3b531 /core/java
parent2150553dc374204a1cb3033ed3fa65c2f22dd5e7 (diff)
downloadframeworks_base-ec84c3a189e4aa70aa6ea8ba712e5a4f260a153b.zip
frameworks_base-ec84c3a189e4aa70aa6ea8ba712e5a4f260a153b.tar.gz
frameworks_base-ec84c3a189e4aa70aa6ea8ba712e5a4f260a153b.tar.bz2
Allow old view hierarchy to be GC'ed more quickly during rotation.
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/animation/ObjectAnimator.java90
-rw-r--r--core/java/android/appwidget/AppWidgetHost.java11
-rw-r--r--core/java/android/view/View.java3
-rw-r--r--core/java/android/widget/AdapterViewAnimator.java6
-rw-r--r--core/java/android/widget/ProgressBar.java4
-rw-r--r--core/java/android/widget/RemoteViewsAdapter.java9
6 files changed, 85 insertions, 38 deletions
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 7f11871..3a292cc 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -18,6 +18,7 @@ package android.animation;
import android.util.Log;
+import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
@@ -28,6 +29,7 @@ import java.util.ArrayList;
* are then determined internally and the animation will call these functions as necessary to
* animate the property.
*
+ * @note Instances of this class hold only a {@link WeakReference} to the target object.
* @see #setPropertyName(String)
*
*/
@@ -35,7 +37,7 @@ public final class ObjectAnimator extends ValueAnimator {
private static final boolean DBG = false;
// The target object on which the property exists, set in the constructor
- private Object mTarget;
+ private WeakReference<Object> mTargetRef;
private String mPropertyName;
@@ -102,6 +104,9 @@ public final class ObjectAnimator extends ValueAnimator {
* @return Method the method associated with mPropertyName.
*/
private Method getPropertyFunction(String prefix, Class valueType) {
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ if (target == null) return null;
+
// TODO: faster implementation...
Method returnVal = null;
String firstLetter = mPropertyName.substring(0, 1);
@@ -114,7 +119,7 @@ public final class ObjectAnimator extends ValueAnimator {
args[0] = valueType;
}
try {
- returnVal = mTarget.getClass().getMethod(setterName, args);
+ returnVal = target.getClass().getMethod(setterName, args);
} catch (NoSuchMethodException e) {
Log.e("ObjectAnimator",
"Couldn't find setter/getter for property " + mPropertyName + ": " + e);
@@ -134,13 +139,14 @@ public final class ObjectAnimator extends ValueAnimator {
* A constructor that takes a single property name and set of values. This constructor is
* used in the simple case of animating a single property.
*
- * @param target The object whose property is to be animated. This object should
- * have a public method on it called <code>setName()</code>, where <code>name</code> is
- * the value of the <code>propertyName</code> parameter.
+ * @param target The object whose property is to be animated. It will be weakly referenced
+ * from the newly-created ObjectAnimator. This object should have a public method on it called
+ * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
+ * parameter.
* @param propertyName The name of the property being animated.
*/
private ObjectAnimator(Object target, String propertyName) {
- mTarget = target;
+ mTargetRef = new WeakReference<Object>(target);
setPropertyName(propertyName);
}
@@ -152,9 +158,10 @@ public final class ObjectAnimator extends ValueAnimator {
* from the target object and property being animated). Therefore, there should typically
* be two or more values.
*
- * @param target The object whose property is to be animated. This object should
- * have a public method on it called <code>setName()</code>, where <code>name</code> is
- * the value of the <code>propertyName</code> parameter.
+ * @param target The object whose property is to be animated. It will be weakly referenced
+ * from the newly-created ObjectAnimator. This object should have a public method on it called
+ * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
+ * parameter.
* @param propertyName The name of the property being animated.
* @param values A set of values that the animation will animate between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
@@ -173,9 +180,10 @@ public final class ObjectAnimator extends ValueAnimator {
* from the target object and property being animated). Therefore, there should typically
* be two or more values.
*
- * @param target The object whose property is to be animated. This object should
- * have a public method on it called <code>setName()</code>, where <code>name</code> is
- * the value of the <code>propertyName</code> parameter.
+ * @param target The object whose property is to be animated. It will be weakly referenced
+ * from the newly-created ObjectAnimator. This object should have a public method on it called
+ * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
+ * parameter.
* @param propertyName The name of the property being animated.
* @param values A set of values that the animation will animate between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
@@ -192,10 +200,10 @@ public final class ObjectAnimator extends ValueAnimator {
* PropertyValuesHolder allows you to associate a set of animation values with a property
* name.
*
- * @param target The object whose property is to be animated. This object should
- * have public methods on it called <code>setName()</code>, where <code>name</code> is
- * the name of the property passed in as the <code>propertyName</code> parameter for
- * each of the PropertyValuesHolder objects.
+ * @param target The object whose property is to be animated. It will be weakly referenced
+ * from the newly-created ObjectAnimator. This object should have public methods on it called
+ * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the
+ * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects.
* @param propertyName The name of the property being animated.
* @param evaluator A TypeEvaluator that will be called on each animation frame to
* provide the ncessry interpolation between the Object values to derive the animated
@@ -218,10 +226,10 @@ public final class ObjectAnimator extends ValueAnimator {
* PropertyValuesHolder allows you to associate a set of animation values with a property
* name.
*
- * @param target The object whose property is to be animated. This object should
- * have public methods on it called <code>setName()</code>, where <code>name</code> is
- * the name of the property passed in as the <code>propertyName</code> parameter for
- * each of the PropertyValuesHolder objects.
+ * @param target The object whose property is to be animated. It will be weakly referenced
+ * from the newly-created ObjectAnimator. This object should have public methods on it called
+ * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the
+ * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects.
* @param values A set of PropertyValuesHolder objects whose values will be animated
* between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
@@ -229,7 +237,7 @@ public final class ObjectAnimator extends ValueAnimator {
public static ObjectAnimator ofPropertyValuesHolder(Object target,
PropertyValuesHolder... values) {
ObjectAnimator anim = new ObjectAnimator();
- anim.mTarget = target;
+ anim.mTargetRef = new WeakReference<Object>(target);
anim.setValues(values);
return anim;
}
@@ -270,7 +278,8 @@ public final class ObjectAnimator extends ValueAnimator {
@Override
public void start() {
if (DBG) {
- Log.d("ObjectAnimator", "Anim target, duration" + mTarget + ", " + getDuration());
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ Log.d("ObjectAnimator", "Anim target, duration" + target + ", " + getDuration());
for (int i = 0; i < mValues.length; ++i) {
PropertyValuesHolder pvh = mValues[i];
ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes;
@@ -297,11 +306,14 @@ public final class ObjectAnimator extends ValueAnimator {
@Override
void initAnimation() {
if (!mInitialized) {
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ if (target == null) return;
+
// mValueType may change due to setter/getter setup; do this before calling super.init(),
// which uses mValueType to set up the default type evaluator.
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setupSetterAndGetter(mTarget);
+ mValues[i].setupSetterAndGetter(target);
}
super.initAnimation();
}
@@ -326,22 +338,26 @@ public final class ObjectAnimator extends ValueAnimator {
/**
* The target object whose property will be animated by this animation
*
- * @return The object being animated
+ * @return The object being animated, or null if the object has been garbage collected.
*/
public Object getTarget() {
- return mTarget;
+ return mTargetRef == null ? null : mTargetRef.get();
}
/**
- * Sets the target object whose property will be animated by this animation
+ * Sets the target object whose property will be animated by this animation. The target
+ * will be weakly referenced from this object.
*
* @param target The object being animated
*/
@Override
public void setTarget(Object target) {
- if (mTarget != target) {
- mTarget = target;
- if (mTarget != null && target != null && mTarget.getClass() == target.getClass()) {
+ final Object currentTarget = mTargetRef == null ? null : mTargetRef.get();
+
+ if (currentTarget != target) {
+ mTargetRef = new WeakReference<Object>(target);
+ if (currentTarget != null && target != null
+ && currentTarget.getClass() == target.getClass()) {
return;
}
// New target type should cause re-initialization prior to starting
@@ -351,19 +367,25 @@ public final class ObjectAnimator extends ValueAnimator {
@Override
public void setupStartValues() {
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ if (target == null) return;
+
initAnimation();
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setupStartValue(mTarget);
+ mValues[i].setupStartValue(target);
}
}
@Override
public void setupEndValues() {
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ if (target == null) return;
+
initAnimation();
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setupEndValue(mTarget);
+ mValues[i].setupEndValue(target);
}
}
@@ -382,9 +404,13 @@ public final class ObjectAnimator extends ValueAnimator {
@Override
void animateValue(float fraction) {
super.animateValue(fraction);
+
+ final Object target = mTargetRef == null ? null : mTargetRef.get();
+ if (target == null) return;
+
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
- mValues[i].setAnimatedValue(mTarget);
+ mValues[i].setAnimatedValue(target);
}
}
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 7730942..9835484 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -214,6 +214,10 @@ public class AppWidgetHost {
}
}
+ /**
+ * Create the AppWidgetHostView for the given widget.
+ * The AppWidgetHost retains a pointer to the newly-created View.
+ */
public final AppWidgetHostView createView(Context context, int appWidgetId,
AppWidgetProviderInfo appWidget) {
AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
@@ -272,6 +276,13 @@ public class AppWidgetHost {
v.viewDataChanged(viewId);
}
}
+
+ /**
+ * Clear the list of Views that have been created by this AppWidgetHost.
+ */
+ protected void clearViews() {
+ mViews.clear();
+ }
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c4bd1de..63a3ff0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7580,6 +7580,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mHardwareLayer.destroy();
mHardwareLayer = null;
}
+ mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_MSG, this);
+ mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_RECT_MSG, this);
+ mCurrentAnimation = null;
}
/**
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index ec8e93c..1b39371 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -986,4 +986,10 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
public void willBeAdvancedByHost() {
}
+
+ @Override
+ protected void onDetachedFromWindow() {
+ mAdapter = null;
+ super.onDetachedFromWindow();
+ }
}
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 5b143fe..ef4e4e0 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -1004,9 +1004,11 @@ public class ProgressBar extends View {
@Override
protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
if (mIndeterminate) {
stopAnimation();
}
+ // This should come after stopAnimation(), otherwise an invalidate message remains in the
+ // queue, which can prevent the entire view hierarchy from being GC'ed during a rotation
+ super.onDetachedFromWindow();
}
}
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index a7bff62..df1f4bf 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -152,6 +152,7 @@ public class RemoteViewsAdapter extends BaseAdapter {
if (callback != null) {
callback.onRemoteAdapterDisconnected();
}
+ adapter.mCache.reset();
}
public IRemoteViewsFactory getRemoteViewsFactory() {
@@ -657,11 +658,9 @@ public class RemoteViewsAdapter extends BaseAdapter {
try {
remoteViews = factory.getViewAt(position);
itemId = factory.getItemId(position);
- } catch (Exception e) {
- // Print the error
- Log.e(TAG, "Error in updateRemoteViews(" + position + "): " +
- e.getMessage());
- e.printStackTrace();
+ } catch (Throwable t) {
+ Log.e(TAG, "Error in updateRemoteViews(" + position + "): " + t.getMessage());
+ t.printStackTrace();
// Return early to prevent additional work in re-centering the view cache, and
// swapping from the loading view