[转]Android实现计时与倒计时(限时抢购)的几种方法

在购物网站的促销活动中一般都有倒计时限制购物时间或者折扣的时间,这些都是如何实现的呢?

在一个安卓客户端项目中恰好遇到了类似的问题,一开始使用的是Timer与 TimerTask, 虽然此方法通用,但后来考虑在安卓中是否有更佳的方案,于是乎共找到以下五种实现方案,另外还有一种使用CountDownTimer进行计时的方面,我会在单独的文章中进行介绍

效果如图:

 

方法一

Timer与TimerTask(Java实现)

[java] view plaincopy
 
  1. public class timerTask extends Activity{    
  2.    
  3.     private int recLen = 11;    
  4.     private TextView txtView;    
  5.     Timer timer = new Timer();    
  6.    
  7.     public void onCreate(Bundle savedInstanceState){    
  8.         super.onCreate(savedInstanceState);    
  9.             
  10.         setContentView(R.layout.timertask);    
  11.         txtView = (TextView)findViewById(R.id.txttime);    
  12.             
  13.         timer.schedule(task, 1000, 1000);       // timeTask    
  14.     }       
  15.    
  16.     TimerTask task = new TimerTask() {    
  17.         @Override    
  18.         public void run() {    
  19.    
  20.             runOnUiThread(new Runnable() {      // UI thread    
  21.                 @Override    
  22.                 public void run() {    
  23.                     recLen--;    
  24.                     txtView.setText(""+recLen);    
  25.                     if(recLen < 0){    
  26.                         timer.cancel();    
  27.                         txtView.setVisibility(View.GONE);    
  28.                     }    
  29.                 }    
  30.             });    
  31.         }    
  32.     };    
  33. }    





方法二
TimerTask与Handler(不用Timer的改进型)

[java] view plaincopy
 
  1. public class timerTask extends Activity{    
  2.     private int recLen = 11;    
  3.     private TextView txtView;    
  4.     Timer timer = new Timer();    
  5.    
  6.     public void onCreate(Bundle savedInstanceState){    
  7.         super.onCreate(savedInstanceState);    
  8.    
  9.         setContentView(R.layout.timertask);    
  10.         txtView = (TextView)findViewById(R.id.txttime);    
  11.    
  12.         timer.schedule(task, 1000, 1000);       // timeTask    
  13.     }       
  14.    
  15.     final Handler handler = new Handler(){    
  16.         @Override    
  17.         public void handleMessage(Message msg){    
  18.             switch (msg.what) {    
  19.             case 1:    
  20.                 txtView.setText(""+recLen);    
  21.                 if(recLen < 0){    
  22.                     timer.cancel();    
  23.                     txtView.setVisibility(View.GONE);    
  24.                 }    
  25.             }    
  26.         }    
  27.     };    
  28.    
  29.     TimerTask task = new TimerTask() {    
  30.         @Override    
  31.         public void run() {    
  32.             recLen--;    
  33.             Message message = new Message();    
  34.             message.what = 1;    
  35.             handler.sendMessage(message);    
  36.         }    
  37.     };    
  38. }    




方法三

[java] view plaincopy
 
  1. Handler与Message(不用TimerTask)  
  2.   
  3. public class timerTask extends Activity{    
  4.     private int recLen = 11;    
  5.     private TextView txtView;    
  6.    
  7.     public void onCreate(Bundle savedInstanceState) {      
  8.         super.onCreate(savedInstanceState);      
  9.    
  10.         setContentView(R.layout.timertask);     
  11.         txtView = (TextView)findViewById(R.id.txttime);    
  12.    
  13.         Message message = handler.obtainMessage(1);     // Message    
  14.         handler.sendMessageDelayed(message, 1000);    
  15.     }      
  16.    
  17.     final Handler handler = new Handler(){    
  18.    
  19.         public void handleMessage(Message msg){         // handle message    
  20.             switch (msg.what) {    
  21.             case 1:    
  22.                 recLen--;    
  23.                 txtView.setText("" + recLen);    
  24.    
  25.                 if(recLen > 0){    
  26.                     Message message = handler.obtainMessage(1);    
  27.                     handler.sendMessageDelayed(message, 1000);      // send message    
  28.                 }else{    
  29.                     txtView.setVisibility(View.GONE);    
  30.                 }    
  31.             }    
  32.    
  33.             super.handleMessage(msg);    
  34.         }    
  35.     };    
  36. }    



方法四

Handler与Thread(不占用UI线程)

[java] view plaincopy
 
  1. public class timerTask extends Activity{    
  2.     private int recLen = 0;    
  3.     private TextView txtView;    
  4.    
  5.     public void onCreate(Bundle savedInstanceState){    
  6.         super.onCreate(savedInstanceState);    
  7.    
  8.         setContentView(R.layout.timertask);    
  9.         txtView = (TextView)findViewById(R.id.txttime);    
  10.             
  11.         new Thread(new MyThread()).start();         // start thread    
  12.     }       
  13.    
  14.     final Handler handler = new Handler(){          // handle    
  15.         public void handleMessage(Message msg){    
  16.             switch (msg.what) {    
  17.             case 1:    
  18.                 recLen++;    
  19.                 txtView.setText("" + recLen);    
  20.             }    
  21.             super.handleMessage(msg);    
  22.         }    
  23.     };    
  24.    
  25.     public class MyThread implements Runnable{      // thread    
  26.         @Override    
  27.         public void run(){    
  28.             while(true){    
  29.                 try{    
  30.                     Thread.sleep(1000);     // sleep 1000ms    
  31.                     Message message = new Message();    
  32.                     message.what = 1;    
  33.                     handler.sendMessage(message);    
  34.                 }catch (Exception e) {    
  35.                 }    
  36.      




方法五

[java] view plaincopy
 
  1. Handler与Runnable(最简单型)    
  2.   
  3. public class timerTask extends Activity{    
  4.     private int recLen = 0;    
  5.     private TextView txtView;    
  6.    
  7.     public void onCreate(Bundle savedInstanceState){    
  8.         super.onCreate(savedInstanceState);    
  9.    
  10.         setContentView(R.layout.timertask);    
  11.         txtView = (TextView)findViewById(R.id.txttime);    
  12.         runnable.run();   
  13.     }       
  14.    
  15.     Handler handler = new Handler();    
  16.     Runnable runnable = new Runnable() {    
  17.         @Override    
  18.         public void run() {    
  19.             recLen++;    
  20.             txtView.setText("" + recLen);    
  21.             handler.postDelayed(this, 1000);    
  22.         }    
  23.     };    
  24. }    




计时与倒计时
方法1,方法2和方法3,都是倒计时
方法4,方法5,都是计时
计时和倒计时,都可使用上述方法实现(代码稍加改动)

UI线程比较
方法1,方法2和方法3,都是在UI线程实现的计时;
方法4和方法5,是另开Runnable线程实现计时

实现方式比较
方法1,采用的是Java实现,即Timer和TimerTask方式;
其它四种方法,都采用了Handler消息处理

推荐使用
如果对UI线程交互要求不很高,可以选择方法2和方法3
如果考虑到UI线程阻塞,严重影响到用户体验,推荐使用方法4,另起线程单独用于计时和其它的逻辑处理

方法5,综合了前几种方法的优点,是最简的

 

 

 

          在逛论坛的时候,看到一个网友提问,说到了CountDownTimer这个类,从名字上面大家就可以看出来,记录下载时间。将后台线程的创建和Handler队列封装成一个方便的类调用。

     查看了一下官方文档,这个类及其简单,只有四个方法,上面都涉及到了onTick,onFinsh、cancel和start。其中前面两个是抽象方法,所以要重写一下。
          下面是官方给的一个小例子:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. new CountdownTimer(30000, 1000) {  
  2.     public void onTick(long millisUntilFinished) {  
  3.         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);  
  4.     }  
  5.     public void onFinish() {  
  6.         mTextField.setText("done!");  
  7.     }  
  8.  }.start();  

 

       直接用的那位网友的代码,自己稍微改动了一下,一个简单的小demo。

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. package cn.demo;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.content.Intent;  
  6. import android.os.CountDownTimer;  
  7. import android.widget.TextView;  
  8. import android.widget.Toast;  
  9. public class NewActivity extends Activity {  
  10.     private MyCount mc;  
  11.     private TextView tv;  
  12.     @Override  
  13.     protected void onCreate(Bundle savedInstanceState) {  
  14.         // TODO Auto-generated method stub  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.main);  
  17.         tv = (TextView)findViewById(R.id.show);  
  18.         mc = new MyCount(30000, 1000);  
  19.         mc.start();  
  20.     }//end func  
  21.   
  22.     /*定义一个倒计时的内部类*/  
  23.     class MyCount extends CountDownTimer {     
  24.         public MyCount(long millisInFuture, long countDownInterval) {     
  25.             super(millisInFuture, countDownInterval);     
  26.         }     
  27.         @Override     
  28.         public void onFinish() {     
  29.             tv.setText("finish");        
  30.         }     
  31.         @Override     
  32.         public void onTick(long millisUntilFinished) {     
  33.             tv.setText("请等待30秒(" + millisUntilFinished / 1000 + ")...");     
  34.             Toast.makeText(NewActivity.this, millisUntilFinished / 1000 + "", Toast.LENGTH_LONG).show();//toast有显示时间延迟       
  35.         }    
  36.     }     
  37. }  

       主要是重写onTick和onFinsh这两个方法,onFinish()中的代码是计时器结束的时候要做的事情;onTick(Long m)中的代码是你倒计时开始时要做的事情,参数m是直到完成的时间,构造方法MyCount()中的两个参数中,前者是倒计的时间数,后者是倒计时onTick事件响应的间隔时间,都是以毫秒为单位。例如要倒计时30秒,每秒中间间隔时间是1秒,两个参数可以这样MyCount(30000,1000)。 将后台线程的创建和Handler队列封装成为了一个方便的类调用。

当你想取消的时候使用mc.cancel()方法就行了。

posted @ 2015-10-13 20:59  牧之丨  阅读(769)  评论(0编辑  收藏  举报