美文网首页Android技术知识Android开发
Android ValueAnimator --内存泄漏

Android ValueAnimator --内存泄漏

作者: h_f | 来源:发表于2019-07-25 09:33 被阅读7次

    不是成功来得太慢,只是下的功夫还不够

    最近在写一个关于贝塞尔曲线水波纹的小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的效果图 \得意

    Screenshot_20190725-090425_ZYTeacherCertification.jpg

    相关文章

      网友评论

        本文标题:Android ValueAnimator --内存泄漏

        本文链接:https://www.haomeiwen.com/subject/kgkcrctx.html