android 中Chronometer类源码分析

来源:互联网 发布:js 随机掉落 编辑:程序博客网 时间:2024/06/06 01:52

1, 概述

Chronometer在平时开发时使用广泛,使用简单, 只需要调用三个简单的方法就可以。

2, Chronometer

Chronometer是TextView的子类,这个组只能以1秒的时间间隔进行计时,并显示出计时结果。使用Handler来实现。

2.1 开发方法

Chronometer开发很简单,

private  Chronometer timer;timer = (Chronometer)findViewById(R.id.timer);  // 定义并获取组件
timer.setBase(SystemClock.elapsedRealtime()); // 设置起始时间timer.start(); // 开始每隔1s开始计时

timer.stop(); // 停止计时

2.2 原理分析

1, setBase

setBase方法如下,

public void setBase(long base) {        mBase = base;  // 设置时间基准        dispatchChronometerTick(); // 回调        updateText(SystemClock.elapsedRealtime()); // 跟新显示    }

setBase方法主要是设置mBase变量,该变量是时间基准。

2, start方法

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

mStarted变量是记录计时是否开始。

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;        }    }

mVisible变量表示该控件是否可见, mRunning变量表示是否在计时。

利用handler进行计时,相当于一个死循环,每隔1s钟执行一次更新和回调。一直到调用stop方法为止。

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

3,stop

public void stop() {        mStarted = false;        updateRunning();    }

将mStarted赋值为空,然后在updateRunning方法中移除消息,这样就终止了计时。

mHandler.removeMessages(TICK_WHAT);// 移除消息。

4, updateText

private synchronized void updateText(long now) {        mNow = 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);    }

首先将当前时间减去基准时间(ms),然后转化为s,转化为特定的时间格式,最后调用setText方法显示到界面。

5, dispatchChronometerTick

void dispatchChronometerTick() {        if (mOnChronometerTickListener != null) {            mOnChronometerTickListener.onChronometerTick(this);        }    }

mOnChronometerTickListener是OnChronometerTickListener对象,而OnChronometerTickListener是Chronometer的内部接口,

public interface OnChronometerTickListener {        void onChronometerTick(Chronometer chronometer);    }

mOnChronometerTickListener变量是通过setOnChronometerTickListener进行赋值的。

public void setOnChronometerTickListener(OnChronometerTickListener listener) {        mOnChronometerTickListener = listener;    }

由此看来,这是一个标准的接口回调方法。

 

如果需要回调,只需要继承OnChronometerTickListener接口,然后调用setOnChronometerTickListener方法,最后实现onChronometerTick方法就可以了。

onChronometerTick方法会在调用start时回调一次,然后每个1s回调一次,一直到调用stop方法为止。

 

小结:

1,Chronometer使用简单,但是只能间隔1s进行计时。

2,有标准的回调方法,并且回调方法也是间隔1s执行一次。

3,使用handler实现,其实开发时也可以利用handler简单的写一个类,这样可以控制间隔时间。

0 0
原创粉丝点击