① android将倒计时做到极致
在开发倒计时功能时往往我们会为了方便直接使用CountDownTimer或者使用Handler做延时来实现,当然CountDownTimer内部封装也是使用的Handler。
如果只是做次数很少的倒计时或者不需要精确的倒计时逻辑那倒没关系,比如说我只要倒计时10秒,或者我大概5分钟请求某个接口
但是如果是需要做精确的倒计时操作,比如说手机发送验证码60秒,那使用现有的倒计时方案就会存在问题。可能有些朋友没有注意到这一点,下面我们就来简单分析一下现有倒计时的问题。
这个可能是用得最多的,因为方便嘛。但其实倒计时每一轮倒计时完之后都是存在误差的,如果看过CountDownTimer的源码你就会知道,他的内部是有做 校准操作 的。(源码很简单这里就不分析了)
但是如果你认真的测试过CountDownTimer,你就会发现,即便它内部有做校准操作,他的没一轮都是有偏差,只是他最后一次倒计时完之后的总共时间和开始倒计时的时间相比没偏差。
什么意思呢,意思就是1秒,2.050秒,3.1秒......,这样的每轮偏差,导致他会出现10.95秒,下一次12秒的情况,那它的回调中如果你直接做取整就会出现少一秒的情况,但实际是没少的。
这只是其中的一个问题,你可以不根据它的回调做展示,自己用一个整形累加做展示也能解决。但是他还有个问题,有概率直接出现跳秒,就是比如3秒,下次直接5秒,这是实际的跳秒,是少了一次回调的那种。
跳秒导致你如果直接使用它可能会大问题,你可能自测的时候没发现,到时一上线应用在用户那概率跳秒,那就蛋疼了。
不搞这么多花里胡哨的,直接使用Handler来实现,会有什么问题。
因为直接使用handler来实现,没有校准操作,每次循环会出现几毫秒的误差,虽然比CountDownTimer的十几毫秒的误差要好, 但是在基数大的倒计时情况下误差会累计,导致最终结果和现实时间差几秒误差,时间越久,误差越大
直接使用Timer也一样,只不过他每轮的误差更小,几轮才有1毫秒的误差,但是没有校准还是会出现误差累计,时间越久误差越大。
既然无法直接使用原生的,那我们就自己做一个。
我们基于Handler进行封装,从上面可以看出主要为了解决两个问题,时间校准和跳秒。自己写一个CountDownTimer
思路就是在倒计时开始前获取一次SystemClock.elapsedRealtime(),没轮倒计时再获取一次SystemClock.elapsedRealtime()相减得到误差,根据delay校准。然后使用while循坏来处理跳秒的操作,与原生的CountDownTimer不同,这里如果跳了多少秒,就会返回多少次回调。
② 接受验证码用什么控件 android
android接收验证码用的控件可以是button,textview 都带有点击效果,如果是输入验证码可以用edittext ,这个没有什么争议,也可以自己定制控件,根据实际的需求来
③ android 用 service 和 CountDownTimer 实现一个倒计时器的功能
在平时我们编程的时候,经常会用到倒计时这个功能,很多人不知道Android已经帮封装好了一个类,往往都自己写。现在发现了这个类,大家共享一下:
在一个TextView不断显示剩下的时间,代码如下:
[java] view plain
private TextView vertifyView;
private CountDownTimer timer = new CountDownTimer(10000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
vertifyView.setText((millisUntilFinished / 1000) + "秒后可重发");
}
@Override
public void onFinish() {
vertifyView.setEnabled(true);
vertifyView.setText("获取验证码");
}
};
调用的时候很简单:timer.start();
最后说明一下:CountDownTimer timer = new CountDownTimer(10000, 1000)中,第一个参数表示总时间,第二个参数表示间隔时间。意思就是每隔一秒会回调一次方法onTick,然后10秒之后会回调onFinish方法。
④ Android实现计时与倒计时的几种方法
Android实现计时与倒计橡册时的五种含模方法:
方梁老宏法一
Handler与Message(不用TimerTask)
public class timerTask extends Activity{
private int recLen = 11;
private TextView txtView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timertask);
txtView = (TextView)findViewById(R.id.txttime);
Message message = handler.obtainMessage(1); // Message
handler.sendMessageDelayed(message, 1000);
}
final Handler handler = new Handler(){
public void handleMessage(Message msg){ // handle message
switch (msg.what) {
case 1:
recLen--;
txtView.setText("" + recLen);
if(recLen > 0){
Message message = handler.obtainMessage(1);
handler.sendMessageDelayed(message, 1000); // send message
}else{
txtView.setVisibility(View.GONE);
}
}
super.handleMessage(msg);
}
};
}
linux
方法二
Handler与Thread(不占用UI线程)
public class timerTask extends Activity{
private int recLen = 0;
private TextView txtView;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.timertask);
txtView = (TextView)findViewById(R.id.txttime);
new Thread(new MyThread()).start(); // start thread
}
final Handler handler = new Handler(){ // handle
public void handleMessage(Message msg){
switch (msg.what) {
case 1:
recLen++;
txtView.setText("" + recLen);
}
super.handleMessage(msg);
}
};
public class MyThread implements Runnable{ // thread
@Override
public void run(){
while(true){
try{
Thread.sleep(1000); // sleep 1000ms
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}catch (Exception e) {
}
}
}
}
}
方法三
Timer与TimerTask(Java实现)
public class timerTask extends Activity{
private int recLen = 11;
private TextView txtView;
Timer timer = new Timer();
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.timertask);
txtView = (TextView)findViewById(R.id.txttime);
timer.schele(task, 1000, 1000); // timeTask
}
TimerTask task = new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() { // UI thread
@Override
public void run() {
recLen--;
txtView.setText(""+recLen);
if(recLen < 0){
timer.cancel();
txtView.setVisibility(View.GONE);
}
}
});
}
};
}
方法四
TimerTask与Handler(不用Timer的改进型)
public class timerTask extends Activity{
private int recLen = 11;
private TextView txtView;
Timer timer = new Timer();
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.timertask);
txtView = (TextView)findViewById(R.id.txttime);
timer.schele(task, 1000, 1000); // timeTask
}
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg){
switch (msg.what) {
case 1:
txtView.setText(""+recLen);
if(recLen < 0){
timer.cancel();
txtView.setVisibility(View.GONE);
}
}
}
};
TimerTask task = new TimerTask() {
@Override
public void run() {
recLen--;
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
};
}
方法五
Handler与Runnable(最简单型)
public class timerTask extends Activity{
private int recLen = 0;
private TextView txtView;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.timertask);
txtView = (TextView)findViewById(R.id.txttime);
handler.postDelayed(runnable, 1000);
}
Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
recLen++;
txtView.setText("" + recLen);
handler.postDelayed(this, 1000);
}
};
}
计时与倒计时
方法1,方法2和方法3,都是倒计时
方法4,方法5,都是计时
计时和倒计时,都可使用上述方法实现(代码稍加改动)
UI线程比较
方法1,方法2和方法3,都是在UI线程实现的计时;
方法4和方法5,是另开Runnable线程实现计时
实现方式比较
方法1,采用的是Java实现,即Timer和TimerTask方式;
其它四种方法,都采用了Handler消息处理
推荐使用
如果对UI线程交互要求不很高,可以选择方法2和方法3
如果考虑到UI线程阻塞,严重影响到用户体验,推荐使用方法4,另起线程单独用于计时和其它的逻辑处理
方法5,综合了前几种方法的优点,是最简的