zoukankan      html  css  js  c++  java
  • 利用反射动态改变android倒计时类CountDownTimer的回调频率

    本文为原创文章,欢迎转载,但请注明出处http://www.cnblogs.com/yexiubiao/archive/2013/01/02/2842026.html,未在文章页面明显位置给出原文连接的,将保留追究法律责任的权利。
     
    在开发中可能我们会遇到这样的需求,
    1,界面上有一个倒计时,当倒计时间剩下不多时,时间开始闪动(颜色红白交替)。如下图:
     
    2,当时间马上就要结束时,闪动频率加快,如图(截图后有些不流畅,实际运行时很流畅的):
     
     
    关于需求1,我们用android自带的倒计时类CountDownTimer很简单地实现,只需要实现抽象类CountDownTimer的两个抽象方法onTick()和onFinish()即可,颜色的话可以用一个标志flag控制交替改变。
    代码:
    //3分钟后到时,每1秒回调一次onTick()
    new CountDownTimer(3 * 60 * 1000, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            //在这里改变界面上的时间
        }
     
        @Override
        public void onFinish() {
            //在这里处理时间到了的逻辑
        }
    }.start();
     
    关于需求2,实现起来有点麻烦。
    首先看下CountDownTimer的构造方法:
    public CountDownTimer(long millisInFuture, long countDownInterval)
    构造CountDownTimer时需传入两个参数,millisInFuture表示倒计时的时长,countDownInterval表示回调间隔(频率)。每隔countDownInterval秒会回调一次onTick()方法。我们马上想到的是 CountDownTimer应该有个setCountDownInterval()方法,可以改变回调间隔countDownInterval的值。但是看了CountDownTimer的源码后,没有发现任何可以改变countDownInterval值的方法。而且成员变量mCountdownInterval是私有的。
     
    这时候我们可能想到以下几种实现方案。
    方案1:当时间小于指定值时,设置一个标志flag,实现类根据这个flag,重新new一个CountDownTimer,并指定新的回调间隔值countDownInterval。但这样实现起来很麻烦,每new一次倒计时,都得实现CountDownTimer的抽象方法,如果项目中有n个地方用到倒计时,那就得重新写n次,不可取。
     
    方案2:构造CountDownTimer类的时候传入的countDownInterval值改为原来的一半,然后在代码中控制,如果是正常显示状态则每隔两次调用一次onTick()方法,当需要加快回调间隔时,每隔一次回调一次onTick()方法,不过这样不太灵活,回调间隔只能是原来的整数倍。而且还得控制标志位flag,也不太可取。
     
    方案3:反射,利用反射动态地改变CountDownTimer类的私有字段mCountdownInterval,这里我抽取成了一个方法,代码如下:
    privatevoid changeCountdownInterval(long time) {
        try {
        // 反射父类CountDownTimer的mCountdownInterval字段,动态改变回调频率
        Class clazz = Class.forName("android.os.CountDownTimer");
        Field field = clazz.getDeclaredField("mCountdownInterval");
        field.setAccessible(true);
        field.set(this, time);
        } catch (Exception e) {
            Log.e("Ye", "反射类android.os.CountDownTimer失败: " + e);
        }
    }
    总结,用方案3的反射实现起来很灵活而且简单,不好的地方是,反射一般尽量少用,因为既然源码将mCountdownInterval定义为私有,而且不暴露修改他的值的方法,就一定有他的原因,以后源码可能会修改私有字段和私有方法,造成反射失效。不过在这里实现方法比较简单灵活,权衡了一下,还是可以使用,最后附上demo ^_^。
     https://files.cnblogs.com/yexiubiao/YeCountDownTimer.rar
  • 相关阅读:
    Permession denied error when use supervisorctl
    alembic 迁移数据库
    Linux VIM常用命令
    AWS EC2 install supervisor
    第一次编程作业
    (转)ubuntu 12 04下安装JDK7
    (转)Java程序利用main函数中args参数实现参数的传递
    Nvidia CUDA 6 Installed In Ubuntu 12.04
    (转)Java程序利用main函数中args参数实现参数的传递
    (转)JAVA路径问题及命令行编译运行基础(linux下)
  • 原文地址:https://www.cnblogs.com/yexiubiao/p/2842026.html
Copyright © 2011-2022 走看看