summaryrefslogtreecommitdiffstats
path: root/core/java/android/animation/Keyframe.java
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2010-10-22 17:54:04 -0700
committerChet Haase <chet@google.com>2010-11-03 17:42:04 -0700
commit7c608f25d494c8a0a671e7373efbb47ca635367e (patch)
treeb3f4c1d8c429ac6523cd41a10d837b6b2f59efad /core/java/android/animation/Keyframe.java
parent8182cd36cfbf5049f72b4be18f67c40ddef89d8b (diff)
downloadframeworks_base-7c608f25d494c8a0a671e7373efbb47ca635367e.zip
frameworks_base-7c608f25d494c8a0a671e7373efbb47ca635367e.tar.gz
frameworks_base-7c608f25d494c8a0a671e7373efbb47ca635367e.tar.bz2
optimizing for primitive types in animations
The animator classes caused autoboxing by converting primitive types (by far the most typical types used in animations) to be converted to their Object equivalents because of various APIs that required Object (like getValue() to get the animated value). This change creates factory methods on some classes instead of the former constructors so that we can create and return private type-specific subclasses which operate directly on the primitive types instead. In particular, float and int are natively supported by the animators now. Support in the APIs for double and long was removed because it seemed like these less common types did not justify the extra baggage of the added API and code. Change-Id: I6008a3883e3d6dd5225005f45f112af148e5a4ea
Diffstat (limited to 'core/java/android/animation/Keyframe.java')
-rw-r--r--core/java/android/animation/Keyframe.java244
1 files changed, 173 insertions, 71 deletions
diff --git a/core/java/android/animation/Keyframe.java b/core/java/android/animation/Keyframe.java
index f9a4f3c..e98719a 100644
--- a/core/java/android/animation/Keyframe.java
+++ b/core/java/android/animation/Keyframe.java
@@ -23,23 +23,27 @@ package android.animation;
* target object will animate between the value at the previous keyframe and the value at the
* next keyframe. Each keyframe also holds an optional {@link TimeInterpolator}
* object, which defines the time interpolation over the intervalue preceding the keyframe.
+ *
+ * <p>The Keyframe class itself is abstract. The type-specific factory methods will return
+ * a subclass of Keyframe specific to the type of value being stored. This is done to improve
+ * performance when dealing with the most common cases (e.g., <code>float</code> and
+ * <code>int</code> values). Other types will fall into a more general Keyframe class that
+ * treats its values as Objects. Unless your animation requires dealing with a custom type
+ * or a data structure that needs to be animated directly (and evaluated using an implementation
+ * of {@link TypeEvaluator}), you should stick to using float and int as animations using those
+ * types have lower runtime overhead than other types.</p>
*/
-public class Keyframe implements Cloneable {
+public abstract class Keyframe implements Cloneable {
/**
* The time at which mValue will hold true.
*/
- private float mFraction;
-
- /**
- * The value of the animation at the time mFraction.
- */
- private Object mValue;
+ float mFraction;
/**
* The type of the value in this Keyframe. This type is determined at construction time,
* based on the type of the <code>value</code> object passed into the constructor.
*/
- private Class mValueType;
+ Class mValueType;
/**
* The optional time interpolator for the interval preceding this keyframe. A null interpolator
@@ -48,23 +52,11 @@ public class Keyframe implements Cloneable {
private TimeInterpolator mInterpolator = null;
/**
- * Private constructor, called from the public constructors with the additional
- * <code>valueType</code> parameter.
- *
- * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
- * of time elapsed of the overall animation duration.
- * @param value The value that the object will animate to as the animation time approaches
- * the time in this keyframe, and the the value animated from as the time passes the time in
- * this keyframe.
- * @param valueType The type of the <code>value</code> object. This is used by the
- * {@link #getValue()} functionm, which is queried by {@link ValueAnimator} to determine
- * the type of {@link TypeEvaluator} to use to interpolate between values.
+ * Flag to indicate whether this keyframe has a valid value. This flag is used when an
+ * animation first starts, to populate placeholder keyframes with real values derived
+ * from the target object.
*/
- private Keyframe(float fraction, Object value, Class valueType) {
- mFraction = fraction;
- mValue = value;
- mValueType = valueType;
- }
+ boolean mHasValue = false;
/**
* Constructs a Keyframe object with the given time and value. The time defines the
@@ -78,28 +70,28 @@ public class Keyframe implements Cloneable {
* the time in this keyframe, and the the value animated from as the time passes the time in
* this keyframe.
*/
- public Keyframe(float fraction, Object value) {
- this(fraction, value, (value != null) ? value.getClass() : Object.class);
+ public static Keyframe ofInt(float fraction, int value) {
+ return new IntKeyframe(fraction, value);
}
/**
- * Constructs a Keyframe object with the given time and float value. The time defines the
+ * Constructs a Keyframe object with the given time. The value at this time will be derived
+ * from the target object when the animation first starts (note that this implies that keyframes
+ * with no initial value must be used as part of an {@link ObjectAnimator}).
+ * The time defines the
* time, as a proportion of an overall animation's duration, at which the value will hold true
* for the animation. The value for the animation between keyframes will be calculated as
* an interpolation between the values at those keyframes.
*
* @param fraction The time, expressed as a value between 0 and 1, representing the fraction
* of time elapsed of the overall animation duration.
- * @param value The value that the object will animate to as the animation time approaches
- * the time in this keyframe, and the the value animated from as the time passes the time in
- * this keyframe.
*/
- public Keyframe(float fraction, Float value) {
- this(fraction, value, Float.class);
+ public static Keyframe ofInt(float fraction) {
+ return new IntKeyframe(fraction);
}
/**
- * Constructs a Keyframe object with the given time and integer value. The time defines the
+ * Constructs a Keyframe object with the given time and value. The time defines the
* time, as a proportion of an overall animation's duration, at which the value will hold true
* for the animation. The value for the animation between keyframes will be calculated as
* an interpolation between the values at those keyframes.
@@ -110,28 +102,28 @@ public class Keyframe implements Cloneable {
* the time in this keyframe, and the the value animated from as the time passes the time in
* this keyframe.
*/
- public Keyframe(float fraction, Integer value) {
- this(fraction, value, Integer.class);
+ public static Keyframe ofFloat(float fraction, float value) {
+ return new FloatKeyframe(fraction, value);
}
/**
- * Constructs a Keyframe object with the given time and double value. The time defines the
+ * Constructs a Keyframe object with the given time. The value at this time will be derived
+ * from the target object when the animation first starts (note that this implies that keyframes
+ * with no initial value must be used as part of an {@link ObjectAnimator}).
+ * The time defines the
* time, as a proportion of an overall animation's duration, at which the value will hold true
* for the animation. The value for the animation between keyframes will be calculated as
* an interpolation between the values at those keyframes.
*
* @param fraction The time, expressed as a value between 0 and 1, representing the fraction
* of time elapsed of the overall animation duration.
- * @param value The value that the object will animate to as the animation time approaches
- * the time in this keyframe, and the the value animated from as the time passes the time in
- * this keyframe.
*/
- public Keyframe(float fraction, Double value) {
- this(fraction, value, Double.class);
+ public static Keyframe ofFloat(float fraction) {
+ return new FloatKeyframe(fraction);
}
/**
- * Constructs a Keyframe object with the given time and integer value. The time defines the
+ * Constructs a Keyframe object with the given time and value. The time defines the
* time, as a proportion of an overall animation's duration, at which the value will hold true
* for the animation. The value for the animation between keyframes will be calculated as
* an interpolation between the values at those keyframes.
@@ -142,40 +134,35 @@ public class Keyframe implements Cloneable {
* the time in this keyframe, and the the value animated from as the time passes the time in
* this keyframe.
*/
- public Keyframe(float fraction, int value) {
- this(fraction, value, int.class);
+ public static Keyframe ofObject(float fraction, Object value) {
+ return new ObjectKeyframe(fraction, value);
}
/**
- * Constructs a Keyframe object with the given time and float value. The time defines the
+ * Constructs a Keyframe object with the given time. The value at this time will be derived
+ * from the target object when the animation first starts (note that this implies that keyframes
+ * with no initial value must be used as part of an {@link ObjectAnimator}).
+ * The time defines the
* time, as a proportion of an overall animation's duration, at which the value will hold true
* for the animation. The value for the animation between keyframes will be calculated as
* an interpolation between the values at those keyframes.
*
* @param fraction The time, expressed as a value between 0 and 1, representing the fraction
* of time elapsed of the overall animation duration.
- * @param value The value that the object will animate to as the animation time approaches
- * the time in this keyframe, and the the value animated from as the time passes the time in
- * this keyframe.
*/
- public Keyframe(float fraction, float value) {
- this(fraction, value, float.class);
+ public static Keyframe ofObject(float fraction) {
+ return new ObjectKeyframe(fraction, null);
}
/**
- * Constructs a Keyframe object with the given time and double value. The time defines the
- * time, as a proportion of an overall animation's duration, at which the value will hold true
- * for the animation. The value for the animation between keyframes will be calculated as
- * an interpolation between the values at those keyframes.
+ * Indicates whether this keyframe has a valid value. This method is called internally when
+ * an {@link ObjectAnimator} first starts; keyframes without values are assigned values at
+ * that time by deriving the value for the property from the target object.
*
- * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
- * of time elapsed of the overall animation duration.
- * @param value The value that the object will animate to as the animation time approaches
- * the time in this keyframe, and the the value animated from as the time passes the time in
- * this keyframe.
+ * @return boolean Whether this object has a value assigned.
*/
- public Keyframe(float fraction, double value) {
- this(fraction, value, double.class);
+ public boolean hasValue() {
+ return mHasValue;
}
/**
@@ -183,18 +170,14 @@ public class Keyframe implements Cloneable {
*
* @return The value for this Keyframe.
*/
- public Object getValue() {
- return mValue;
- }
+ public abstract Object getValue();
/**
* Sets the value for this Keyframe.
*
* @param value value for this Keyframe.
*/
- public void setValue(Object value) {
- mValue = value;
- }
+ public abstract void setValue(Object value);
/**
* Gets the time for this keyframe, as a fraction of the overall animation duration.
@@ -248,9 +231,128 @@ public class Keyframe implements Cloneable {
}
@Override
- public Keyframe clone() {
- Keyframe kfClone = new Keyframe(mFraction, mValue, mValueType);
- kfClone.setInterpolator(mInterpolator);
- return kfClone;
+ public abstract Keyframe clone();
+
+ /**
+ * This internal subclass is used for all types which are not int or float.
+ */
+ static class ObjectKeyframe extends Keyframe {
+
+ /**
+ * The value of the animation at the time mFraction.
+ */
+ Object mValue;
+
+ ObjectKeyframe(float fraction, Object value) {
+ mFraction = fraction;
+ mValue = value;
+ mHasValue = (value != null);
+ mValueType = mHasValue ? value.getClass() : Object.class;
+ }
+
+ public Object getValue() {
+ return mValue;
+ }
+
+ public void setValue(Object value) {
+ mValue = value;
+ mHasValue = (value != null);
+ }
+
+ @Override
+ public ObjectKeyframe clone() {
+ ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), mValue);
+ kfClone.setInterpolator(getInterpolator());
+ return kfClone;
+ }
+ }
+
+ /**
+ * Internal subclass used when the keyframe value is of type int.
+ */
+ static class IntKeyframe extends Keyframe {
+
+ /**
+ * The value of the animation at the time mFraction.
+ */
+ int mValue;
+
+ IntKeyframe(float fraction, int value) {
+ mFraction = fraction;
+ mValue = value;
+ mValueType = int.class;
+ mHasValue = true;
+ }
+
+ IntKeyframe(float fraction) {
+ mFraction = fraction;
+ mValueType = int.class;
+ }
+
+ public int getIntValue() {
+ return mValue;
+ }
+
+ public Object getValue() {
+ return mValue;
+ }
+
+ public void setValue(Object value) {
+ if (value != null && value.getClass() == Integer.class) {
+ mValue = ((Integer)value).intValue();
+ mHasValue = true;
+ }
+ }
+
+ @Override
+ public IntKeyframe clone() {
+ IntKeyframe kfClone = new IntKeyframe(getFraction(), mValue);
+ kfClone.setInterpolator(getInterpolator());
+ return kfClone;
+ }
+ }
+
+ /**
+ * Internal subclass used when the keyframe value is of type float.
+ */
+ static class FloatKeyframe extends Keyframe {
+ /**
+ * The value of the animation at the time mFraction.
+ */
+ float mValue;
+
+ FloatKeyframe(float fraction, float value) {
+ mFraction = fraction;
+ mValue = value;
+ mValueType = float.class;
+ mHasValue = true;
+ }
+
+ FloatKeyframe(float fraction) {
+ mFraction = fraction;
+ mValueType = float.class;
+ }
+
+ public float getFloatValue() {
+ return mValue;
+ }
+
+ public Object getValue() {
+ return mValue;
+ }
+
+ public void setValue(Object value) {
+ if (value != null && value.getClass() == Float.class) {
+ mValue = ((Float)value).floatValue();
+ mHasValue = true;
+ }
+ }
+
+ @Override
+ public FloatKeyframe clone() {
+ FloatKeyframe kfClone = new FloatKeyframe(getFraction(), mValue);
+ kfClone.setInterpolator(getInterpolator());
+ return kfClone;
+ }
}
}