Android实现多个倒计时优化与源代码分析
由于之前有个项目需求是须要时时刻去更新UI倒计时,之前想到的,这简单嘛,用计时或者Handler就能够搞定,并且性能也不错,可是需求要ListView,什么,?大量的View都须要,那Handle处理不好会挂的啊,那轮训呢,?太消耗内存和Cpu,突然之前仅仅有想到用Handle去处理,可是Item太多怎样管理呢.?
带着这种问题,思考着纠结着,今天无意中看到一个源代码还不错,
这个类是Google原生提供的数字时钟,能够实现时时刻刻的更新,我想里面肯定封装了一些实现的逻辑就跟着開始研究学习,以下是该类的主要结构:
/**
* Like AnalogClock, but digital. Shows seconds.
*
* FIXME: implement separate views for hours/minutes/seconds, so
* proportional fonts don't shake rendering
*/ public class DigitalClock extends TextView { Calendar mCalendar;
private final static String m12 = "h:mm:ss aa";
private final static String m24 = "k:mm:ss";
private FormatChangeObserver mFormatChangeObserver; private Runnable mTicker;
private Handler mHandler; private boolean mTickerStopped = false; String mFormat; public DigitalClock(Context context) {
super(context);
initClock(context);
} public DigitalClock(Context context, AttributeSet attrs) {
super(context, attrs);
initClock(context);
} private void initClock(Context context) {
Resources r = mContext.getResources(); if (mCalendar == null) {
mCalendar = Calendar.getInstance();
} mFormatChangeObserver = new FormatChangeObserver(); //格式观察者,開始第一眼我看到这儿以为是通过观察者去实现的,结果仅仅是一个格式的观察.
getContext().getContentResolver().registerContentObserver( //注冊
Settings.System.CONTENT_URI, true, mFormatChangeObserver); setFormat(); // 设置格式
}
/**
*这种方法就是更新的核心,该方法是能正常的call onDraw或者onMeasure后便会回调.
*
*/
@Override
protected void onAttachedToWindow() {
mTickerStopped = false;
super.onAttachedToWindow();
mHandler = new Handler(); // 用于Post一个runable. /**
* requests a tick on the next hard-second boundary
*/
mTicker = new Runnable() {
public void run() {
if (mTickerStopped) return;
mCalendar.setTimeInMillis(System.currentTimeMillis()); // 之前创建日历对象获取时间.
setText(DateFormat.format(mFormat, mCalendar)); // 设置时间
invalidate(); // 更新UI
long now = SystemClock.uptimeMillis();
long next = now + (1000 - now % 1000);// 这儿算法不错,保证一秒更新一次,
mHandler.postAtTime(mTicker, next);
}
};
mTicker.run();
} @Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mTickerStopped = true;// 保证复用的时候,runable被系统回收.
} /**
* Pulls 12/24 mode from system settings
*/
private boolean get24HourMode() {
return android.text.format.DateFormat.is24HourFormat(getContext());
} private void setFormat() {
if (get24HourMode()) {
mFormat = m24;
} else {
mFormat = m12;
}
} private class FormatChangeObserver extends ContentObserver {
public FormatChangeObserver() {
super(new Handler());
} @Override
public void onChange(boolean selfChange) {
setFormat();
}
} @Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(DigitalClock.class.getName());
} @Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(DigitalClock.class.getName());
}
}
看到OnAttachedToWindow方法后,能够借鉴出来一个自己定义的好的写法.我就不用Calender去获取时间更新,把它封装出来给用户使用.我就临时仅仅贴出核心代码吧
@Override
protected void onAttachedToWindow() {
mTickerStopped = false;
super.onAttachedToWindow();
mHandler = new Handler(); /**
* requests a tick on the next hard-second boundary
*/
mTicker = new Runnable() {
public void run() {
if (mTickerStopped)
return;
long currentTime = System.currentTimeMillis();
if (currentTime / 1000 == endTime / 1000 - 1 * 60) { // 判定是否到了指定时间
mClockListener.remainOneMinutes(); // 指定时间的CallBack
}
long distanceTime = endTime - currentTime;// 计算差值
distanceTime /= 1000; // 转为秒
if (distanceTime == 0) {
setText("00:00:00");
onDetachedFromWindow(); // 保证该runnable不在被继续执行.
mClockListener.timeEnd(); // 结束call back.
} else if (distanceTime < 0) {
setText("00:00:00");
} else {
setText(dealTime(distanceTime));// 设置倒计时.
}
invalidate();
long now = SystemClock.uptimeMillis();
long next = now + (1000 - now % 1000);// 够不够一秒,保证一秒更新一次
mHandler.postAtTime(mTicker, next);
}
};
mTicker.run();
}
上面是核心展示UI工具类,真正的回收机制在以下处理,
在ListView中设置一个setRecyclerListener,该监听会依据手指滑动一个View移除屏幕外的时候会callback.
@Override
public void onMovedToScrapHeap(View view) {
try {
((ClockView)((LinearLayout) view).getChildAt(0)).changeTicker();//寻找时钟,并启动.
}catch (Exception e){
e.printStackTrace();
}
}
回收的推断,
<pre name="code" class="java">/**
* 回收后启动
*/
public void changeTicker() {
mTickerStopped = !mTickerStopped;
if (!mTickerStopped) {
mHandler.post(mTicker);
}else{
mHandler.removeCallbacks(mTicker);
}
}
在适配器中:
@Override
public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder;
if (null == convertView) {
holder = new ViewHolder();
convertView = View.inflate(context, R.layout.item_list, null);
holder.cv = (ClockView) convertView.findViewById(R.id.cv);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
holder.cv.changeTicker(); // 从回收中拿的时候启动一次.
}
holder.cv.setEndTime(mTimes.get(position));
return convertView;
}
Android实现多个倒计时优化与源代码分析的更多相关文章
- Android应用程序进程启动过程的源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址: http://blog.csdn.net/luoshengyang/article/details/6747696 Android 应用程序框架层创 ...
- Android系统进程Zygote启动过程的源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6768304 在Android系统中,所有的应用 ...
- Android应用程序安装过程源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6766010 Android系统在启动的过程中, ...
- Android应用Activity、Dialog、PopWindow、Toast窗体加入机制及源代码分析
[工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处.尊重劳动成果] 1 背景 之所以写这一篇博客的原因是由于之前有写过一篇<Android应用setCont ...
- Android KLog源代码分析
Android KLog源代码分析 Android KLog源代码分析 代码结构 详细分析 BaseLog FileLog JsonLog XmlLog 核心文件KLogjava分析 遇到的问题 一直 ...
- android webview开发问题及优化汇总
我们在native与网页相结合开发的过程中,难免会遇到关于WebView一些共通的问题.就我目前开发过程中遇到的问题以及最后得到的优化方案都将在这里列举出来.有些是老生常谈,有些则是个人摸索得出解决方 ...
- [FMX] Android APP 启动黑屏优化补丁
使用说明 *************************************************** Android APP 启动黑屏优化补丁 作者: Swish, YangYxd 201 ...
- Android 中View的绘制机制源代码分析 三
到眼下为止,measure过程已经解说完了,今天開始我们就来学习layout过程.只是在学习layout过程之前.大家有没有发现我换了编辑器,哈哈.最终下定决心从Html编辑器切换为markdown编 ...
- Android系统默认Home应用程序(Launcher)的启动过程源代码分析
在前面一篇文章中,我们分析了Android系统在启动时安装应用程序的过程,这些应用程序安装好之后,还需要有一个 Home应用程序来负责把它们在桌面上展示出来,在Android系统中,这个默认的Home ...
随机推荐
- Python应该怎样实现快速入门?
作为一名Python爱好者,我也想跟大家分享分享我自学Python的一些小经验.搬来你的小板凳,听听看吧.也许,你会很有收获,也许你也走上了自学Python的不归路.开讲啦~ 首先,你要有自信心,要明 ...
- BZOJ 4464 旅行时的困惑 最小流
题面: Waldives 有 N 个小岛.目前的交通系统中包含 N-1 条快艇专线,每条快艇 专线连接两个岛.这 N-1条快艇专线恰好形成了一棵树. 由于特殊的原因,所有N-1条快艇专线都是单向的.这 ...
- 秋招复习-C++( 一)
Linux/Unix编程部分 1.进程间通信方式:信号,信号量,消息队列,共享内存,套接字Socket 2.ipcs: Linux/Unix下的命令,可以用来查看当前系统中所使用的进程间通信方式的各种 ...
- 测试Mysql悲观锁
- 数据结构代码实现之队列的链表实现(C/C++)
上班闲着无聊,一直想着要开始写博客,但又不知道写什么.最近又回顾了下数据结构的知识,那就从数据结构开始吧. 前言 关于C语言结构体的知识以及队列的特性请读者自行了解,此处不做过多解释,嘻嘻. 同时此篇 ...
- typeof instanceof操作符的相关知识
数据类型 ECMAScript中有5中基本数据类型:Undefined Null Boolean Number String. Typeof运算符 对一个值使用typeof操作符可能返回下列某个字符串 ...
- 【20】AngularJS 参考手册
AngularJS 参考手册 AngularJS 指令 用到的 AngularJS 指令 : 指令 描述 解析 ng-app 定义应用程序的根元素. 指令 ng-bind 绑定 HTML 元素到应用程 ...
- cmake打印变量值
看下面的例子,我们在cmake定义了一个变量“USER_KEY”,并打印此变量值.status表示这是一般的打印信息,我们还可以设置为“ERROR”,表示这是一种错误打印信息. SET(USER_KE ...
- 树剖 lca
GeneralLiu 橙边为轻边 红边为重边 绿数为每个点的 top 橙数为每个点的编号 步骤 1 先预处理 每个点的 deep深度 size子树大小 dad父节点 2 再预处理 每个点的 to ...
- hihoCoder#1077 RMQ问题再临-线段树
原题地址 终于做到线段树的题了,因为建树.更新.查询都是递归操作,所以其实挺好写的. 用数组存的树,记得MAX_NODE开成两倍叶节点数大小,否则RE啊..不要问我是怎么知道的. 代码: #inclu ...