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 ...
随机推荐
- asp.net中js和jquery调用ashx的不同方法分享,需要的朋友可以参考一下
asp.net中js和jquery调用ashx的不同方法分享,需要的朋友可以参考一下 =============js================ 复制代码代码如下: var xhr = n ...
- android网络图片自动轮播 githhub地址
https://github.com/panxw/android-image-indicator
- webpack4前端工程化教程(一)
-本文作为webpack小白入门文章,会详细地介绍webpack的用途.具体的安装步骤.注意事项.一些基本的配置项,并且会以一个具体的项目实例来介绍如何使用webpack.另外,本文会简单地介绍一些最 ...
- mac apache 配置
mac系统自带apache这无疑给广大的开发朋友提供了便利,接下来是针对其中的一些说明 一.自带apache相关命令 1. sudo apachectl start 启动服务,需要权限,就是你计算机的 ...
- MySQL与MyBatis中的查询记录
1.时间段查询 MySQL:select * from table where ctime >= CURDATE() and ctime <DATE_SUB(CURDATE(),INTER ...
- 你知道你常用的dos和linux命令吗?
功能 Linux MS-DOS 进入到该目录 cd cd 列举文件 ls dir 创建目录 mkdir mkdir 清除屏幕 clear cls 复制文件 cp copy 移动文件 mv move 删 ...
- ORM之创建数据库
ORM之创建数据库 样板:创建表名为UserInfo的表,表的主键可自行写,Django的ORM也可自行创建. from django.db import models class UserInfo( ...
- String replaceAll-正则匹配-截取以指定字符开头,以指定字符结尾的字符串
scala代码块 截取以某个字符开头,以某个字符结尾的字符串 def main(args: Array[String]): Unit = { val s = "{{a61,a2,a3},{b ...
- oracle exp direct 执行机制
使用直接导出模式 direct=y exp 比传统模式导出快一倍 oracle提供2种模式导出表数据,传统模式CONVENTIONAL PATH和直接模式DIRECT PATH,有direct指定. ...
- 南邮CTF密码学,mixed_base64
# -*- coding:utf-8 -*- from base64 import * flag = open("code.txt").readline() # 读取密文 for ...