Handler vs Timer,究竟该用哪个?
Handler vs Timer
在我们Android开发过程中,经常需要执行一些短周期的定时任务,这时候有两个选择Timer或者Handler。然而个人认为:Handler在多个方面比Timer更为优秀,更推荐使用。
一.易用性
1. 可重复执行
- Handler可以重复执行某个任务。
- Timer若在某个任务执行/取消之后,再次执行则会抛出一个IllegalStateException异常。为了避免这个异常,需要重新创建一个Timer对象。
2. 周期可调整
若想要执行一个越来越快的定时任务,Handler可以做到,而Timer则消耗较大。
- Handler
private Handler handler = new Handler();
int mDelayTime = 1000;
private Runnable runnable = new Runnable() {
public void run() {
update();
if (mDelayTime > 0) {
handler.postDelayed(this,mDelayTime);
mDelayTime -= 100;
}
}
};
handler.postDelayed(runnable,1000);
如以上例子,就可以实现对周期的动态调整。
- Timer的scheduleAtFixedRate(TimerTask task, long delay, long period)只能执行固定周期的任务,所以不可以动态地调整周期。若想要动态调整,则需要在执行玩一个定时器任务后,再启动一个新的任务时设置新的时间。
3. UI界面更新
- Handler:在创建的时候可以指定所在的线程,一般在Activity中构建的,即主线程上,所以可以在回调方法中很方便的更新界面。
- Timer:异步回调,所以必须借助Handler去更新界面,不方便。
既然都得用Handler去更新界面了,为何不如把定时的功能也交给Handler去做呢?
二.内存占比
Timer比Handler更占内存。
接下来的Demo例子通过两种方法循环地打印日志,然后通过MAT插件来查看这两个类所需要调用的对象所产生的占比。
int mCount = 0;
private void startTimer() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
Log.i("JKL", "" + mCount);
mCount++;
}
}, 0, 200);
}
private void startHandler() {
final Handler mHandler = new Handler();
mHandler.post(new Runnable() {
@Override
public void run() {
Log.i("JKL", "" + mCount);
mCount++;
mHandler.postDelayed(this, 200);
}
});
}
可以通过创建一个新的Android工程,在onCreate方法中调用以上startTimer或startHandler任意一个方法来测试。
以下是MAT的测试结果。
Timer相关对象的内存占比

共有5个对象,占用1192B。
Handler相关对象的内存占比

我们可以看到上面有2个Handler,这时候你是否会疑惑呢?其实一个是我们生成的Handler,另外一个是Activity默认生成的,存在于ViewRootImp中,这涉及到ViewTree的知识,此处不便展开。
不过我们可以知道,我们自己构建的Handler,最多也就只占64B。

在使用Handler的时候,还需要用到Runnable,不过也只占了16B。
所以,使用Handler的方式来作为定时器,最多也就是80B。
以上可以得出结论,相比起Timer方式的定时器占用1192B,Handler的方式占用资源会小很多,只有1/60。
所以Handler的方式比较节省内存。
写到这里,想到一个点,Timer是创建一个线程去计数的,而Handler是在默认主线程运行的。假若Handler也用一个异步线程去运行,会不会耗很多资源呢?
以下是测试代码:
private void startHandler() {
HandlerThread thread = new HandlerThread("Test");
thread.start();
final Handler mHandler = new Handler(thread.getLooper());
mHandler.post(new Runnable() {
@Override
public void run() {
Log.i("JKL", "" + mCount);
mCount++;
mHandler.postDelayed(this, 200);
}
});
}
以上用一个HandlerThread来启动一个新的线程。再看看内存占比:

可以看到HandlerThread也只是占了96B的内存。
综上所述,Handler内存占比低!而且低了不少。
无论从易用性还是内存占比出发,Handler更胜一筹.
Handler vs Timer,究竟该用哪个?的更多相关文章
- android Handler vs Timer
Handler vs Timer 在我们Android开发过程中,经常需要执行一些短周期的定时任务,这时候有两个选择Timer或者Handler.然而个人认为: Handler 在多个方面比Timer ...
- handler和Timer的用法
final Handler handler = new Handler(){public void handleMessage(Message msg){if (msg.what == 0x123){ ...
- 使用Handler和Timer+Timertask实现简单的图片轮播
布局文件就只放了一个简单的ImageView,就不展示了. 下面是Activity package com.example.administrator.handlerthreadmessagedemo ...
- Timer.4 - Using a member function as a handler
In this tutorial we will see how to use a class member function as a callback handler. The program s ...
- android 定时器(Handler Timer Thread AlarmManager CountDownTimer)
Android实现定时任务一般会使用以上(Handler Timer Thread AlarmManager CountDownTimer)五种方式.当然还有很多组合使用(比如Handler+Thre ...
- 倒计时 总结 Timer Handler CountDownTimer RxJava MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 倒计时实现方案总结 Timer Handler
利用Timer实现倒计时 @BindView(R.id.send) Button send;//发送验证码 private int time = 60;//倒计时 private Timer time ...
- Android学习之Handler消息传递机制
Android只允许UI线程修改Activity里的UI组件.当Android程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户 ...
- 从源码角度深入理解Handler
为了获得良好的用户体验,Android不允许开发者在UI线程中调用耗时操作,否则会报ANR异常,很多时候,比如我们要去网络请求数据,或者遍历本地文件夹都需要我们在新线程中来完成,新线程中不能更新UI, ...
随机推荐
- 心路历程——毕设程序mr跑不通的问题
这个bug改了实在是太多天了,前前后后折腾了太久,最后多谢@CC学长的帮助,找到了问题,才终于跑通了!!!这里记录一下这个bug我前后改的过程,引以为戒! 毕设中需要进行mapreduce进行数据清洗 ...
- (转)Window 上安装Node.js
window上安装nodejs非常的简单,next,next就行了,环境变量都是自动配置,不明白为毛java不这样 Window 上安装Node.js http://www.runoob.com/no ...
- 解决Eclipse下不自动拷贝apk到模拟器问题( The connection to adb is down, and a severe error has occured)
如题 解决方案如下: 1.先把eclipse关闭.2.在管理器转到你的android SDK 的platform-tools下3.键入adb kill-server ,如果adb关闭了会提示 serv ...
- Git和Repo管理使用
Git和Repo管理使用简要介绍 http://blog.csdn.net/stevenhu_223/article/details/8828130 多仓库代码管理器Repo的安装,使用以及服务器搭建 ...
- vue - .babelrc
描述:bable-es2015以及babel本身组件在新版本要求的外部配置文件. { "presets": [ ["env", { "modules& ...
- Hibernate关系映射(三) 多对多
一.使用用户User和Role实现多对多的示例 User.java,实现对Role的引用 package com.lxit.entity; import java.util.HashSet; impo ...
- jQuery切换事件
有html页面内容如下: <body> <h5 id="hh">关于jQuery的介绍</h5> <p id="p1" ...
- python小写转大写金额
python小写转大写金额 摘自:http://shine-it.net/index.php?topic=14575.0 def _rmb_upper(self, value): "&quo ...
- mount挂载WINDOWS分区和目录
转自:http://blog.163.com/sg_liao/blog/static/29577083200942811445981/ 一,挂载共享目录 sudo mount -t cifs -o ...
- sql中判断某个字符串是否包含一个字符串
如果想从SQL Server中查询包含某个关键字的东东,怎么查询呢? 一般有两个方法: 1.用like——select * from tablename where field1 like like ...