• [转]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()方法就行了。

  • 相关阅读:
    python 类和实例
    python 装饰器
    *args和**kwargs:
    定义函数
    python 调用函数
    python lambda表达式
    java-commons-HttpClient超时设置setConnectionTimeout和setSoTimeout
    python 获取响应头
    Freesshd Permission denied (publickey).
    update 嵌套优化
  • 原文地址:https://www.cnblogs.com/exmyth/p/4875881.html
Copyright © 2020-2023  润新知