在使用ValueAnimator或者ObjectAnimator时(ObjectAnimator继承ValueAnimator),如果没有及时做cancel取消动画,就可能造成内存泄露。因为在cancel方法里,最后调用了endAnimation(); ,在endAnimation里,有个AnimationHandler的单例,会持有属性动画对象的引用,属性对象持有view的引用,view持有activity引用,所以导致的内存泄露。
分析:
动画开启
objectAnimator.start()
objectAnimator继承ValueAnimator,接下来查看ValueAnimator的start方法。
@Override
public void start() {
AnimationHandler.getInstance().autoCancelBasedOn(this);
if (DBG) {
Log.d(LOG_TAG, "Anim target, duration: " + getTarget() + ", " + getDuration());
for (int i = 0; i < mValues.length; ++i) {
PropertyValuesHolder pvh = mValues[i];
Log.d(LOG_TAG, " Values[" + i + "]: " +
pvh.getPropertyName() + ", " + pvh.mKeyframes.getValue(0) + ", " +
pvh.mKeyframes.getValue(1));
}
}
super.start();
}
ValueAnimator的start方法
@Override
public void start() {
start(false);
}
private void start(boolean playBackwards) {
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
********省略部分代码***********
addAnimationCallback(0);
********省略部分代码***********
}
private void addAnimationCallback(long delay) {
if (!mSelfPulse) {
return;
}
getAnimationHandler().addAnimationFrameCallback(this, delay);
}
可以看到这里有一个AnimationHandler的单例
public AnimationHandler getAnimationHandler() {
return AnimationHandler.getInstance();
}
public static AnimationHandler getInstance() {
if (sAnimatorHandler.get() == null) {
sAnimatorHandler.set(new AnimationHandler());
}
return sAnimatorHandler.get();
}
ValueAnimator实现了AnimationFrameCallback接口,AnimationHandler持有了动画对象的引用
public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
if (mAnimationCallbacks.size() == 0) {
getProvider().postFrameCallback(mFrameCallback);
}
if (!mAnimationCallbacks.contains(callback)) {
mAnimationCallbacks.add(callback);
}
if (delay > 0) {
mDelayedCallbackStartTime.put(callback, (SystemClock.uptimeMillis() + delay));
}
}
接下来我们看看取消动画的代码
@Override
public void cancel() {
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
// If end has already been requested, through a previous end() or cancel() call, no-op
// until animation starts again.
if (mAnimationEndRequested) {
return;
}
********省略部分代码***********
endAnimation();
}
private void endAnimation() {
if (mAnimationEndRequested) {
return;
}
removeAnimationCallback();
mAnimationEndRequested = true;
********省略部分代码***********
}
可以看到在调用cancel的时候,将AnimationHandler持有的引用移除
private void removeAnimationCallback() {
if (!mSelfPulse) {
return;
}
getAnimationHandler().removeCallback(this);
}
public void removeCallback(AnimationFrameCallback callback) {
mCommitCallbacks.remove(callback);
mDelayedCallbackStartTime.remove(callback);
int id = mAnimationCallbacks.indexOf(callback);
if (id >= 0) {
mAnimationCallbacks.set(id, null);
mListDirty = true;
}
}
总结:ObjectAnimator继承了ValueAnimator,ValueAnimator实现了AnimationFrameCallback接口,在开启动画的时候,AnimationHandler持有了ValueAnimator或ObjectAnimator的引用,因此在activity销毁的时候要保证属性动画执行完毕或者手动调用cancel方法。
————————————————
版权声明:本文为CSDN博主「缘尽&渺如梦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_36356379/article/details/97125062