[转载]利用反射动态改变android倒计时类CountDownTimer的回调频率 – 叶秀标 – 博客园.
在开发中可能我们会遇到这样的需求,
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 ^_^。
http://files.cnblogs.com/yexiubiao/YeCountDownTimer.rar