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更胜一筹.

最新文章

  1. node-webkit 使用requirejs 小结
  2. libtool: line 990: g++: command not found的解决
  3. 用于模式匹配的String方法
  4. AndFix热修复 —— 实战与源码解析
  5. 中继器、集线器(HUB)、网桥、交换机、路由器比较
  6. 常用dos命令 如查询端口号是否被占用
  7. JS&CSS文件请求合并及压缩处理研究(三)
  8. hdu 5469 Antonidas (dfs+剪枝)2015 ACM/ICPC Asia Regional Shanghai Online
  9. Entity Framewor中的 Migration
  10. NET Core MVC 在linux上的创建及发布
  11. 201521123028 《Java程序设计》第3周学习总结
  12. 情景linux--如何摆脱深路径的频繁切换烦恼?
  13. 快递查询 C#
  14. linux----------CentOS的一些除了yum安装以外的基本操作命令。
  15. CSS 图像左右对齐
  16. 二层环路保护,SEP多实例的配置
  17. css隐藏滚动条依旧可以滚动
  18. Python 列表(List)包含的函数与方法
  19. Linux/Centos下使用mtr做路由图进行网络分析
  20. U3D对齐功能

热门文章

  1. TCP的状态(SYN,FIN等)
  2. Junit测试Spring应用Dubbo测试框架之-Excel 工具类
  3. 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-为什么无法打开官方范例的项目,打开tszip文件时提示尝试越过结尾怎么办
  4. C#秘密武器之特性
  5. spring下载和安装
  6. win7 linux双系统删除linux
  7. Cacti监控MySQL实现过程中碰到的问题解汇总
  8. C# 字符串数组转换为整形数组
  9. Sublime Text 3 JS 格式化插件 JsFormat的配置使用
  10. 自定义asp.net mvc Filter 过滤器