Android计时器的三种实现方式(Chronometer、Timer、handler)_Android

本文实例为大家分享了Android计时器的三种方法,具体内容如下

目录:

1、借助Timer实现

2、调用handler.sendMessagedely(Message msg, long delayMillis)

3、借助布局Chronometer

1、借助Timer实现

(1) 布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >

  <TextView
   android:id="@+id/timerView"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_gravity="center_horizontal"
   android:textSize="60sp" />

 </LinearLayout>

布局文件很简单,就是一个TextView用来显示计时时间。下面看一下Activity里的逻辑实现:

(2)Activity文件

public class MyChronometer extends Activity {
   private TextView timerView;
   private long baseTimer;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
     setContentView(R.layout.chrono);
     MyChronometer.this.baseTimer = SystemClock.elapsedRealtime();
     timerView = (TextView) this.findViewById(R.id.timerView);
     final Handler startTimehandler = new Handler(){
     public void handleMessage(android.os.Message msg) {
         if (null != timerView) {
           timerView.setText((String) msg.obj);
         }
       }
     };
     new Timer("开机计时器").scheduleAtFixedRate(new TimerTask() {
       @Override
       public void run() {
         int time = (int)((SystemClock.elapsedRealtime() - MyChronometer.this.baseTimer) / 1000);
         String hh = new DecimalFormat("00").format(time / 3600);
         String mm = new DecimalFormat("00").format(time % 3600 / 60);
         String ss = new DecimalFormat("00").format(time % 60);
         String timeFormat = new String(hh + ":" + mm + ":" + ss);
         Message msg = new Message();
         msg.obj = timeFormat;
         startTimehandler.sendMessage(msg);
       }

     }, 0, 1000L);
     super.onCreate(savedInstanceState);
   }

新开一个定时器(Timer), 在子线程中获取开机时间并转成字符串格式, 利用handler传回UI线程显示。

(3)运行结果:

2.调用handler.sendMessagedely(Message msg, long delayMillis)

(1) 布局文件与方法1 相同,运行结果与方法1 相同

(2)Activity文件

public class MyChronometer extends Activity {
   private TextView timerView;
   private long baseTimer;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
     setContentView(R.layout.chrono);
     MyChronometer.this.baseTimer = SystemClock.elapsedRealtime();
     timerView = (TextView) this.findViewById(R.id.timerView);
     Handler myhandler = new Handler(){
       public void handleMessage(android.os.Message msg) {
         if (0 == MyChronometer.this.baseTimer) {
           MyChronometer.this.baseTimer = SystemClock.elapsedRealtime();
         }

         int time = (int)((SystemClock.elapsedRealtime() - MyChronometer.this.baseTimer) / 1000);
         String hh = new DecimalFormat("00").format(time / 3600);
         String mm = new DecimalFormat("00").format(time % 3600 / 60);
         String ss = new DecimalFormat("00").format(time % 60);
         if (null != MyChronometer.this.timerView) {
           timerView.setText(hh + ":" + mm + ":" + ss);
         }
         sendMessageDelayed(Message.obtain(this, 0x0), 1000);
       }
     };
     myhandler.sendMessageDelayed(Message.obtain(myhandler, 0x0), 1000);
     super.onCreate(savedInstanceState);
   }

sendMessageDelayed (Message msg, long delayMillis):在 delayMillis/1000 秒后发送消息 msg。

在Handler 的 handleMessage()方法中调用sendMessageDelayed方法, 巧妙的实现了循环。需要注意的是,在Handler外要调用一次startTimehandler.sendMessageDelayed(Message.obtain(startTimehandler, 0x0), 1000);  以作为循环的入口。

3.借助布局Chronometer

(1) 布局文件

 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical" >

   <Chronometer
     android:id="@+id/chronometer"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center_horizontal"
     android:textSize="60sp" />

</LinearLayout>

布局Chronometer继承自TextView

(2)Activity文件

 public class MyChronometer extends Activity {

   Chronometer chronometer;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
     setContentView(R.layout.chrono);
     chronometer = (Chronometer) this.findViewById(R.id.chronometer);
     chronometer.setBase(SystemClock.elapsedRealtime());
     chronometer.start();
     super.onCreate(savedInstanceState);
   }
 }

 逻辑代码很简单,调用chronometer.start()就可以开始计时。

chronometer.setBase(long base):设置起始计时点,这里设置的是获取开机时间。

chronometer.start():以上面setBase()设置的时间点为起始点,开始计时,看一下start()的源码就知道了:

public void start() {
  mStarted = true;
  updateRunning();
 }

调用了updateRunning(), 跟入updateRunning()方法:

   private void updateRunning() {
     boolean running = mVisible && mStarted;
     if (running != mRunning) {
       if (running) {
         updateText(SystemClock.elapsedRealtime());
         dispatchChronometerTick();
         mHandler.sendMessageDelayed(Message.obtain(mHandler, TICK_WHAT), 1000);
       } else {
         mHandler.removeMessages(TICK_WHAT);
       }
       mRunning = running;
     }
   }

   private Handler mHandler = new Handler() {
     public void handleMessage(Message m) {
       if (mRunning) {
         updateText(SystemClock.elapsedRealtime());
         dispatchChronometerTick();
         sendMessageDelayed(Message.obtain(this, TICK_WHAT), 1000);
       }
     }
   };

用updateText()方法设置时间显示。 至于计时循环机制,和方法二相同,同样是调用了handler的handMessageDelayed方法。

(3)运行结果:

注意:最后说一个关于Chronometer类的常见问题,看到很多人都问用Chronometer类如何设置格式HH:MM:SS的时间。(如果您有此问题请继续看,没有问题请忽略)

问这个问题的童鞋先看一下官方文档的描述:

 If the format string is null, or if you never call setFormat(), the Chronometer will simply display the timer value in "MM:SS" or "H:MM:SS" form.

也就是说默认情况下,使用的格式是"MM:SS" 或者 "H:MM:SS", 然后有童鞋又会问:那到底是"MM:SS" 还是 "H:MM:SS"。我们先看一下源码:

updateText():

 private synchronized void updateText(long now) {
     long seconds = now - mBase;
     seconds /= 1000;
     String text = DateUtils.formatElapsedTime(mRecycle, seconds);

     if (mFormat != null) {
       Locale loc = Locale.getDefault();
       if (mFormatter == null || !loc.equals(mFormatterLocale)) {
         mFormatterLocale = loc;
         mFormatter = new Formatter(mFormatBuilder, loc);
       }
      mFormatBuilder.setLength(0);
       mFormatterArgs[0] = text;
       try {
         mFormatter.format(mFormat, mFormatterArgs);
         text = mFormatBuilder.toString();
       } catch (IllegalFormatException ex) {
         if (!mLogged) {
           Log.w(TAG, "Illegal format string: " + mFormat);
           mLogged = true;
         }
       }
     }    

  setText(text);
   }

调用了DateUtils.formatElapsedTime, 看一下DateUtils.formatElapsedTime里面都有啥:

 public static String formatElapsedTime(StringBuilder recycle, long elapsedSeconds) {
     Formatter f = new Formatter(sb, Locale.getDefault());
     initFormatStrings();
     if (hours > 0) {
       return f.format(sElapsedFormatHMMSS, hours, minutes, seconds).toString();
     } else {
       return f.format(sElapsedFormatMMSS, minutes, seconds).toString();
     }
   }

代码较多,我就挑重点截取了,仔细看看上面哪个if(){}else{}语句,你肯定就恍然大悟了吧?

为了我们理论的正确性,将方法三 Activity中的代码稍作修改:

chronometer.setBase(-18000000);

运行结果如下:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, 计时器
, handler
, timer
Chronometer
handler计时器、java timer计时器、python 计时器 timer、timer计时器、android计时器timer,以便于您获取更多的相关知识。

时间: 2024-09-20 00:32:19

Android计时器的三种实现方式(Chronometer、Timer、handler)_Android的相关文章

Android计时器的三种实现方式(Chronometer、Timer、handler)

本文实例为大家分享了Android计时器的三种方法,具体内容如下 目录: 1.借助Timer实现 2.调用handler.sendMessagedely(Message msg, long delayMillis) 3.借助布局Chronometer 1.借助Timer实现 (1) 布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http:/

Android XML数据的三种解析方式_Android

本篇文章包含以下内容:      XML数据的Dom解析      XML数据的Sax解析      XML数据的Pull解析      Activity中使用三种解析      Sax解析与Pull解析区别 三种解析方式的步骤: 1.在Assets文件夹中模拟创建XML数据 2.创建对应XML的Bean对象 3.开始解析 XML数据的Dom解析 DOM解析XML文件时,会将XML文件的所有内容读取到内存中(内存的消耗比较大),然后允许您使用DOM API遍历XML树.检索所需的数据 一.在As

Android 文件下载三种基本方式

一.自己封装URLConnection 连接请求类 public void downloadFile1() { try{ //下载路径,如果路径无效了,可换成你的下载路径 String url = "http://c.qijingonline.com/test.mkv"; String path = Environment.getExternalStorageDirectory().getAbsolutePath(); final long startTime = System.cur

无线路由器的三种加密方式

  无线路由器主要提供了三种无线安全类型:WPA-PSK/WPA2-PSK.WPA/WPA2 以及WEP.不同的安全类型下,安全设置项不同. 1. WPA-PSK/WPA2-PSK WPA-PSK/WPA2-PSK安全类型其实是WPA/WPA2的一种简化版本,它是基于共享密钥的WPA模式,安全性很高,设置也比较简单,适合普通家庭用户和小型企业使用.其具体设置项见下图所示: 认证类型: 该项用来选择系统采用的安全模式,即自动.WPA-PSK.WPA2-PSK. 自动:若选择该项,路由器会根据主机请

[Android]Android数据的四种存储方式

Context ctx=MainActivity.this; ContentResolver resolver =ctx.getContentResolver(); Uri uri=Uri.parse("content://com.example.androidtestdemo"); Cursor c = resolver.query(uri, null, null, null, null); c.moveToFirst(); while(!c.isAfterLast()){ for(

Linq to Sql : 三种事务处理方式

原文:Linq to Sql : 三种事务处理方式     Linq to SQL支持三种事务处理模型:显式本地事务.显式可分发事务.隐式事务.(from  MSDN: 事务 (LINQ to SQL)).MSDN中描述得相对比较粗狂,下面就结合实例来对此进行阐述. 0. 测试环境 OS Windows Server 2008 Enterprise + sp1 IDE Visual Studio 2008, .net framework 3.5 + SP1 DB SQL Server 2000

IIS下PHP的三种配置方式对比_php技巧

在Windows IIS 6.0下配置PHP,通常有CGI.ISAPI和FastCGI三种配置方式,这三种模式都可以在IIS 6.0下成功运行,下面我就讲一下这三种方式配置的区别和性能上的差异.   1.CGI(通用网关接口/Common Gateway Interface)一般是可执行程序,例如EXE文件,和WEB服务器各自占据着不同的进程,而且一般一个CGI程序只能处理一个用户请求.这样,当用户请求数量非常多时,会大量占用系统的资源,如内存.CPU时间等,造成效能低下.   2.ISAPI(

java代码中init method和destroy method的三种使用方式

在Java的实际开发过程中,我们可能常常需要使用到init method和destroy method,比如初始化一个对象(bean)后立即初始化(加载)一些数据,在销毁一个对象之前进行垃圾回收等等. 周末对这两个方法进行了一点学习和整理,倒也不是专门为了这两个方法,而是在巩固spring相关知识的时候提到了,然后感觉自己并不是很熟悉这个,便好好的了解一下. 根据特意的去了解后,发现实际上可以有三种方式来实现init method和destroy method. 要用这两个方法,自然先要知道这两

php实现递归的三种基本方式_php技巧

递归函数是我们常用到的一类函数,最基本的特点是函数自身调用自身,但必须在调用自身前有条件判断,否则无限无限调用下去.实现递归函数可以采取什么方式呢?本文列出了三种基本方式.理解其原来需要一定的基础知识水品,包括对全局变量,引用,静态变量的理解,也需对他们的作用范围有所理解.递归函数也是解决无限级分类的一个很好地技巧.如果对无限级分类感兴趣,请参照php利用递归函数实现无限级分类.我习惯套用通俗的话解释复杂的道理,您确实不明白请参见手册. 利用引用做参数 先不管引用做不做参数,必须先明白引用到底是