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 ...
随机推荐
- 【计算机网络】3.2 无连接运输:UDP
第三章第二节 无连接运输:UDP UDP(用户数据报协议,User Datagram Protocol),它只是做了运输层协议能够做的最少工作,除了多路复用和多路分解及一些差错检测外,它几乎没有做任何 ...
- 网络测速命令--speedtest
网络测速 speedtest-cli 顾名思义,这个命令为网络测速命令,基于Python编写,测试系统网络的上传下载速度,GitHub托管的项目地址,以下列出常见的用法 安装命令 pip instal ...
- 笔试算法题(40):后缀数组 & 后缀树(Suffix Array & Suffix Tree)
议题:后缀数组(Suffix Array) 分析: 后缀树和后缀数组都是处理字符串的有效工具,前者较为常见,但后者更容易编程实现,空间耗用更少:后缀数组可用于解决最长公共子串问题,多模式匹配问题,最长 ...
- yii1框架,事务使用方法
Yii1框架事务操作方法如下: $transaction= Yii::app()->db->beginTransaction();//创建事务 $transaction->commi ...
- openwrt 配置samba && ubuntu 配置samba
前言:在修改opkg update的下载目录,公司里不能连外网,尝试用samba. 配置samba很简单,修改/etc/config/samba文件,拷贝一下share项,再改一下name就可以了. ...
- 安装lnmp
一.yum安装php 1.更新更新yum源:rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rp ...
- xcap发包工具的简单使用3(报文描述)
之前详细介绍了如何构造以及发送报文,现在简单对报文描述一下 1.Ethernet MAC:填写报文目的mac和源mac地址 Vlan:支持单vlan,QinQ,如果有更多的vlan,请填写在“More ...
- B. Mr. Kitayuta's Colorful Graph,二维并查集,一个简单变形就可以水过了~~
B. Mr. Kitayuta's Colorful Graph -> Link <- 题目链接在上面,题目比较长,就不贴出来了,不过这是道很好的题,很多方法都可以做,真心邀请去A了这 ...
- [ZJOI2010] 数字统计
[ZJOI2010] 数字统计 题目 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. INPUT 输入文件中仅包含一行两个整数a.b,含义如上所述 OUTP ...
- MTK平台 GPU 相关知识
一.什么是Render script,以及mtk平台GPU support情况 [DESCRIPTION] 1.什么是RenderScript ? 2.RenderScript 干什么? 3.MTK平 ...