diff options
author | Chet Haase <chet@google.com> | 2014-09-05 16:53:25 -0700 |
---|---|---|
committer | Chet Haase <chet@google.com> | 2014-09-10 21:21:53 +0000 |
commit | 6f6578e81c1df207da47e2e1337382341f271206 (patch) | |
tree | d6ce571eb3ce3a5997e05e4624c3364a593a9cb1 /graphics | |
parent | 9da6c905772c6ba1d7dff91593ba9f9cf85d2483 (diff) | |
download | frameworks_base-6f6578e81c1df207da47e2e1337382341f271206.zip frameworks_base-6f6578e81c1df207da47e2e1337382341f271206.tar.gz frameworks_base-6f6578e81c1df207da47e2e1337382341f271206.tar.bz2 |
Use constant state in AnimatedVectorDrawable
Complex animated vector drawables can be expensive to load due to
sub-optimal parsing of the String-based pathData. Suffering that penalty
every time the same drawable is loaded (such as material-themed
ProgressBars) is painful.
The new approach caches constant state of both the VectorDrawable (including
the pathData geometry) and the animators (which includes potentially expensive
path-based interpolators).
issue #17366831 Material ProgressBar taking 200+ms to inflate
Change-Id: Iba3b541e24cfce8c07f5aa9fe6aa7d7b92b2fe1c
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java | 47 | ||||
-rw-r--r-- | graphics/java/android/graphics/drawable/VectorDrawable.java | 17 |
2 files changed, 55 insertions, 9 deletions
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index e5e2f18..49e8b9d 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -27,6 +27,7 @@ import android.graphics.ColorFilter; import android.graphics.Outline; import android.graphics.PorterDuff; import android.graphics.Rect; +import android.util.ArrayMap; import android.util.AttributeSet; import android.util.Log; @@ -131,7 +132,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false; - private final AnimatedVectorDrawableState mAnimatedVectorState; + private AnimatedVectorDrawableState mAnimatedVectorState; + + private boolean mMutated; public AnimatedVectorDrawable() { mAnimatedVectorState = new AnimatedVectorDrawableState( @@ -140,7 +143,6 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { private AnimatedVectorDrawable(AnimatedVectorDrawableState state, Resources res, Theme theme) { - // TODO: Correctly handle the constant state for AVD. mAnimatedVectorState = new AnimatedVectorDrawableState(state); if (theme != null && canApplyTheme()) { applyTheme(theme); @@ -148,8 +150,17 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { } @Override + public Drawable mutate() { + if (!mMutated && super.mutate() == this) { + mAnimatedVectorState = new AnimatedVectorDrawableState(mAnimatedVectorState); + mMutated = true; + } + return this; + } + + @Override public ConstantState getConstantState() { - return null; + return mAnimatedVectorState; } @Override @@ -311,14 +322,31 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { int mChangingConfigurations; VectorDrawable mVectorDrawable; ArrayList<Animator> mAnimators; + ArrayMap<Animator, String> mTargetNameMap; public AnimatedVectorDrawableState(AnimatedVectorDrawableState copy) { if (copy != null) { mChangingConfigurations = copy.mChangingConfigurations; - // TODO: Make sure the constant state are handled correctly. - mVectorDrawable = new VectorDrawable(); - mVectorDrawable.setAllowCaching(false); - mAnimators = new ArrayList<Animator>(); + if (copy.mVectorDrawable != null) { + mVectorDrawable = (VectorDrawable) copy.mVectorDrawable.getConstantState().newDrawable(); + mVectorDrawable.mutate(); + mVectorDrawable.setAllowCaching(false); + mVectorDrawable.setBounds(copy.mVectorDrawable.getBounds()); + } + if (copy.mAnimators != null) { + final int numAnimators = copy.mAnimators.size(); + mAnimators = new ArrayList<Animator>(numAnimators); + mTargetNameMap = new ArrayMap<Animator, String>(numAnimators); + for (int i = 0; i < numAnimators; ++i) { + Animator anim = copy.mAnimators.get(i); + Animator animClone = anim.clone(); + String targetName = copy.mTargetNameMap.get(anim); + Object targetObject = mVectorDrawable.getTargetByName(targetName); + animClone.setTarget(targetObject); + mAnimators.add(animClone); + mTargetNameMap.put(animClone, targetName); + } + } } } @@ -346,7 +374,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { private void setupAnimatorsForTarget(String name, Animator animator) { Object target = mAnimatedVectorState.mVectorDrawable.getTargetByName(name); animator.setTarget(target); + if (mAnimatedVectorState.mAnimators == null) { + mAnimatedVectorState.mAnimators = new ArrayList<Animator>(); + mAnimatedVectorState.mTargetNameMap = new ArrayMap<Animator, String>(); + } mAnimatedVectorState.mAnimators.add(animator); + mAnimatedVectorState.mTargetNameMap.put(animator, name); if (DBG_ANIMATION_VECTOR_DRAWABLE) { Log.v(LOGTAG, "add animator for target " + name + " " + animator); } diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index a07ccc4..65ab454 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -629,6 +629,15 @@ public class VectorDrawable extends Drawable { mThemeAttrs = copy.mThemeAttrs; mChangingConfigurations = copy.mChangingConfigurations; mVPathRenderer = new VPathRenderer(copy.mVPathRenderer); + if (copy.mVPathRenderer.mFillPaint != null) { + mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint); + } + if (copy.mVPathRenderer.mStrokePaint != null) { + mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint); + } + if (copy.mVPathRenderer.mColorFilter != null) { + mVPathRenderer.mColorFilter = copy.mVPathRenderer.mColorFilter; + } mTint = copy.mTint; mTintMode = copy.mTintMode; mAutoMirrored = copy.mAutoMirrored; @@ -700,8 +709,8 @@ public class VectorDrawable extends Drawable { */ // Variables that only used temporarily inside the draw() call, so there // is no need for deep copying. - private final Path mPath = new Path(); - private final Path mRenderPath = new Path(); + private final Path mPath; + private final Path mRenderPath; private static final Matrix IDENTITY_MATRIX = new Matrix(); private final Matrix mFinalPathMatrix = new Matrix(); @@ -724,6 +733,8 @@ public class VectorDrawable extends Drawable { public VPathRenderer() { mRootGroup = new VGroup(); + mPath = new Path(); + mRenderPath = new Path(); } public void setRootAlpha(int alpha) { @@ -736,6 +747,8 @@ public class VectorDrawable extends Drawable { public VPathRenderer(VPathRenderer copy) { mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap); + mPath = new Path(copy.mPath); + mRenderPath = new Path(copy.mRenderPath); mBaseWidth = copy.mBaseWidth; mBaseHeight = copy.mBaseHeight; mViewportWidth = copy.mViewportWidth; |