Android計(jì)時器的三種實(shí)現(xiàn)方式(Chronometer、Timer、handler)
本文實(shí)例為大家分享了Android計(jì)時器的三種方法,具體內(nèi)容如下
目錄:
1、借助Timer實(shí)現(xiàn)
2、調(diào)用handler.sendMessagedely(Message msg, long delayMillis)
3、借助布局Chronometer
1、借助Timer實(shí)現(xiàn)
(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用來顯示計(jì)時時間。下面看一下Activity里的邏輯實(shí)現(xiàn):
(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("開機(jī)計(jì)時器").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), 在子線程中獲取開機(jī)時間并轉(zhuǎn)成字符串格式, 利用handler傳回UI線程顯示。
(3)運(yùn)行結(jié)果:
2.調(diào)用handler.sendMessagedely(Message msg, long delayMillis)
(1) 布局文件與方法1 相同,運(yùn)行結(jié)果與方法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 秒后發(fā)送消息 msg。
在Handler 的 handleMessage()方法中調(diào)用sendMessageDelayed方法, 巧妙的實(shí)現(xiàn)了循環(huán)。需要注意的是,在Handler外要調(diào)用一次startTimehandler.sendMessageDelayed(Message.obtain(startTimehandler, 0x0), 1000); 以作為循環(huán)的入口。
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); } }
邏輯代碼很簡單,調(diào)用chronometer.start()就可以開始計(jì)時。
chronometer.setBase(long base):設(shè)置起始計(jì)時點(diǎn),這里設(shè)置的是獲取開機(jī)時間。
chronometer.start():以上面setBase()設(shè)置的時間點(diǎn)為起始點(diǎn),開始計(jì)時,看一下start()的源碼就知道了:
public void start() { mStarted = true; updateRunning(); }
調(diào)用了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()方法設(shè)置時間顯示。 至于計(jì)時循環(huán)機(jī)制,和方法二相同,同樣是調(diào)用了handler的handMessageDelayed方法。
(3)運(yùn)行結(jié)果:
注意:最后說一個關(guān)于Chronometer類的常見問題,看到很多人都問用Chronometer類如何設(shè)置格式HH:MM:SS的時間。(如果您有此問題請繼續(xù)看,沒有問題請忽略)
問這個問題的童鞋先看一下官方文檔的描述:
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.
也就是說默認(rèn)情況下,使用的格式是"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); }
調(diào)用了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(); } }
代碼較多,我就挑重點(diǎn)截取了,仔細(xì)看看上面哪個if(){}else{}語句,你肯定就恍然大悟了吧?
為了我們理論的正確性,將方法三 Activity中的代碼稍作修改:
chronometer.setBase(-18000000);
運(yùn)行結(jié)果如下:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- android之計(jì)時器(Chronometer)的使用以及常用的方法
- Android時分秒計(jì)時器的兩種實(shí)現(xiàn)方法
- android計(jì)時器,時間計(jì)算器的實(shí)現(xiàn)方法
- android開發(fā)教程之間隔執(zhí)行程序(android計(jì)時器)
- Android實(shí)現(xiàn)的秒表計(jì)時器示例
- Android 編程下的計(jì)時器代碼
- Android編程之簡單計(jì)時器實(shí)現(xiàn)方法
- Android開發(fā)實(shí)現(xiàn)的計(jì)時器功能示例
- Android中CountDownTimer倒計(jì)時器用法實(shí)例
- Android實(shí)現(xiàn)計(jì)時器功能
相關(guān)文章
Android SQLite數(shù)據(jù)庫連接實(shí)現(xiàn)登錄功能
這篇文章主要為大家詳細(xì)介紹了Android SQLite數(shù)據(jù)庫連接實(shí)現(xiàn)登錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-10-10Android4.4 WebAPI實(shí)現(xiàn)拍照上傳功能
這篇文章主要介紹了Android4.4 WebAPI實(shí)現(xiàn)拍照上傳功能,本文給出4.4版本后拍照上傳的具體實(shí)現(xiàn)方法,感興趣的小伙伴們可以參考一下2016-07-07Android開發(fā)中ViewPager實(shí)現(xiàn)多頁面切換效果
ViewPager用于實(shí)現(xiàn)多頁面的切換效果,該類存在于Google的兼容包里面,所以在引用時記得在BuilldPath中加入“Android-support-v4.jar”。具體詳情大家可以參考下本文2016-11-11Android自定義SeekBar實(shí)現(xiàn)滑動驗(yàn)證且不可點(diǎn)擊
這篇文章主要為大家詳細(xì)介紹了Android自定義SeekBar實(shí)現(xiàn)滑動驗(yàn)證且不可點(diǎn)擊,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-03-03Flutter 快速實(shí)現(xiàn)聊天會話列表效果示例詳解
這篇文章主要為大家介紹了Flutter 快速實(shí)現(xiàn)聊天會話列表效果示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Android 使用VideoView播放MP4的簡單實(shí)現(xiàn)
這篇文章主要介紹了Android 使用VideoView播放MP4的簡單實(shí)現(xiàn),實(shí)現(xiàn)簡單的播放功能,播放手機(jī)本地的MP4文件,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05詳解flutter中常用的container layout實(shí)例
這篇文章主要為大家介紹了詳解flutter中常用的container layout實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Android獲取分享應(yīng)用列表詳解及實(shí)例
這篇文章主要介紹了Android獲取分享應(yīng)用列表詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-04-04Android AsyncTask 后監(jiān)聽異步加載完畢的動作詳解
這篇文章主要介紹了Android 使用AsyncTask 后監(jiān)聽異步加載完畢的動作的相關(guān)資料,需要的朋友可以參考下2016-11-11