属性动画AnimatorListener中onAnimation

2019-01-04  本文已影响0人  碧桃鹦鹉

在项目中有一个这样的场景,A动画播放完之后立即播放B动画。间隔一定时间之后,B动画reverse反转播放,播放完之后再reverse播放A动画。效果看上去是一个整体的顺序执行的动画。 我的做法是,为A动画B动画分别设定一个ValueAnimator,然后再各自的动画监听AnimatorListener中控制谁先谁后。但是在A动画的AnimatorListener的onAnimationEnd回调中去判断A动画isRunning()时,居然是输出的true,而且是在有些设备上会出现这样的结果。

valueAnimator = ValueAnimator.ofFloat(0f, 1f);
valueAnimator.setDuration(1000);
valueAnimator.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {
    }
    @Override
    public void onAnimationEnd(Animator animation) {
        System.out.println("valueAnimator.isRunning() " + valueAnimator.isRunning());
    }
    @Override
    public void onAnimationCancel(Animator animation) {
    }
    @Override
    public void onAnimationRepeat(Animator animation) {
    }
});
valueAnimator.start();

运行在两台测试手机,一台是华为PRA-AL00输出false,一台是OPPO A37m输出true。这样的问题说大不大,说小不小。在End的时候,询问是否在运行,居然是确定的答案,很不可思议,就打算研究一下这个事。
查看ValueAnimator的isRunning()源码:

@Override
public boolean isRunning() {
    return mRunning;
}

发现只是返回mRunning这个字段,推测应该是mRunning这个字段没在合适的时候修改为false,那就查看一下mRunning这个字段什么时候被设置为false。由于在断点调试的过程中,调试的代码行号和实际的对不上,所以根本找不到代码执行到哪里,看其他网友分享解决行号对不上的时候,有的人说如果按着解决方法做了还是对不上的话,那就是手机厂商深度定制了系统,修改了源码。。。所以通过查看源码的方式就不行了。
那也要找到是什么情况下导致这个返回结果不对,所以我尝试在onAnimationEnd中停一秒再获取:

 @Override
 public void onAnimationEnd(Animator animation) {
     System.out.println("valueAnimator.isRunning() " + valueAnimator.isRunning());
     new Thread(new Runnable() {
         @Override
         public void run() {
             try {
                 Thread.sleep(1000);
                 System.out.println("thread valueAnimator.isRunning() " + valueAnimator.isRunning());
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
     }).start();
 }

输出结果为:

01-04 21:25:11.805 21056-21056/com.liuan.face.face I/System.out: valueAnimator.isRunning() true
01-04 21:25:12.806 21056-21307/com.liuan.face.face I/System.out: thread valueAnimator.isRunning() false

看来还是改变成false了 可能是获取的时机不对,那到底是什么时候呢?在刚才的线程中增加:

while (i < 1000) {
    System.out.println("thread while valueAnimator.isRunning() " + valueAnimator.isRunning());
    i++;
}

输出结果为 1000行的false。看来不是时机不对,可能是开了线程的原因。看看到底是什么时候true变成了false:

@Override
public void onAnimationEnd(Animator animation) {
    System.out.println("valueAnimator.isRunning() " + valueAnimator.isRunning());
    for (int i = 0; i < 1000; i++) {
        System.out.println("for valueAnimator.isRunning() " + valueAnimator.isRunning());
    }
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("while valueAnimator.isRunning() " + valueAnimator.isRunning());
        }
    }).start();
}

输出结果为1000个true之后是一个false。
继续修改代码为让主线程的和子线程的同时交错输出:

@Override
public void onAnimationEnd(Animator animation) {
    System.out.println("valueAnimator.isRunning() " + valueAnimator.isRunning());
    new Thread(new Runnable() {
        int i = 0;
        @Override
        public void run() {
            while (i < 1000) {
                System.out.println("while valueAnimator.isRunning() " + valueAnimator.isRunning());
                i++;
            }
        }
    }).start();
    for (int i = 0; i < 1000; i++) {
        System.out.println("for valueAnimator.isRunning() " + valueAnimator.isRunning());
    }
}

这时候就有意思了,输出结果为两种不规则交替输出,并且结果都是true。在这之前以为开线程才是唯一保险的方法,现在看来,虽然子线程中获取到了false,但是之后在主线程里再去获取的时候,mRunning又被赋值为true。
根据上面的实验推测,可能是手机厂商对源码的深度改造,也可能是手机内核对线程的分配方式不同,也可能是两个原因同时存在,导致这样“奇妙”的现象。
但是功能毕竟要实现,源码不靠谱,那就靠自己,增加一个boolean值用来判断:

valueAnimator.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {
        isRunning = true;
    }
    @Override
    public void onAnimationEnd(Animator animation) {
        isRunning = false;
    }
    @Override
    public void onAnimationCancel(Animator animation) {
    }
    @Override
    public void onAnimationRepeat(Animator animation) {
    }
});

这时候在onAnimationEnd之后不是调valueAnimator.isRunning(),而是获取isRunning的值,这样就确保不会有问题了。

伸懒腰

上一篇下一篇

猜你喜欢

热点阅读