不是成功来得太慢,只是下的功夫还不够
最近在写一个关于贝塞尔曲线水波纹的小DEMO,发现关闭当前视图时报出内存泄漏的问题,检查下内存泄漏信息,经过排查发现是ValueAnimator的监听事件引起的,
先上解决方法:
在Activity/Fragment销毁时调用如下方法:
public void release(){
if (valueAnimator != null) {
valueAnimator.cancel();
valueAnimator.removeAllUpdateListeners();
}
}
找到问题就好办了,查源码
private void start(boolean playBackwards) {
if (Looper.myLooper() == null) {
throw new AndroidRuntimeException("Animators may only be run on Looper threads");
}
mReversing = playBackwards;
mSelfPulse = !mSuppressSelfPulseRequested;
// Special case: reversing from seek-to-0 should act as if not seeked at all.
if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0) {
if (mRepeatCount == INFINITE) {
// Calculate the fraction of the current iteration.
float fraction = (float) (mSeekFraction - Math.floor(mSeekFraction));
mSeekFraction = 1 - fraction;
} else {
mSeekFraction = 1 + mRepeatCount - mSeekFraction;
}
}
mStarted = true;
mPaused = false;
mRunning = false;
mAnimationEndRequested = false;
// Resets mLastFrameTime when start() is called, so that if the animation was running,
// calling start() would put the animation in the
// started-but-not-yet-reached-the-first-frame phase.
mLastFrameTime = -1;
mFirstFrameTime = -1;
mStartTime = -1;
addAnimationCallback(0);
if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
// If there's no start delay, init the animation and notify start listeners right away
// to be consistent with the previous behavior. Otherwise, postpone this until the first
// frame after the start delay.
startAnimation();
if (mSeekFraction == -1) {
// No seek, start at play time 0. Note that the reason we are not using fraction 0
// is because for animations with 0 duration, we want to be consistent with pre-N
// behavior: skip to the final value immediately.
setCurrentPlayTime(0);
} else {
setCurrentFraction(mSeekFraction);
}
}
}
检查发现在ValueAnimator start()方法中有个addAnimationCallback(0);
调用,继续检查发现
private void addAnimationCallback(long delay) {
if (!mSelfPulse) {
return;
}
getAnimationHandler().addAnimationFrameCallback(this, delay);
}
/**
* @return The {@link AnimationHandler} that will be used to schedule updates for this animator.
* @hide
*/
public AnimationHandler getAnimationHandler() {
return AnimationHandler.getInstance();
}
这里就发现问题了,AnimationHandler.getInstance();
这个是单例获取,所以在退出Activity时,ValueAnimator没有被释放,找到问题就好办了,就在Activity或者Fragment被销毁时,主动把动画监听取消掉。最后上一下我Demo的效果图 \得意
网友评论