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

版权声明:欢迎自由转载-非商用-非衍生-保持署名。作者:Benhero,博客地址:http://www.cnblogs.com/benhero/

【转】Timer还是Handler的更多相关文章

  1. Android计时器TimerTask,Timer,Handler

    Android计时器TimerTask,Timer,若要在TimerTask中更新主线程UI,鉴于Android编程模型不允许在非主线程中更新主线程UI,因此需要结合Android的Handler实现 ...

  2. android Handler vs Timer

    Handler vs Timer 在我们Android开发过程中,经常需要执行一些短周期的定时任务,这时候有两个选择Timer或者Handler.然而个人认为: Handler 在多个方面比Timer ...

  3. Handler Timer TimerTask ScheduledExecutor 循环任务解析

    使用Handler执行循环任务 private Handler handler = new Handler(); private int mDelayTime = 1000; private Runn ...

  4. 倒计时 总结 Timer Handler CountDownTimer RxJava MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  5. 倒计时实现方案总结 Timer Handler

    利用Timer实现倒计时 @BindView(R.id.send) Button send;//发送验证码 private int time = 60;//倒计时 private Timer time ...

  6. Handler vs Timer,究竟该用哪个?

    Handler vs Timer 在我们Android开发过程中,经常需要执行一些短周期的定时任务,这时候有两个选择Timer或者Handler.然而个人认为:Handler在多个方面比Timer更为 ...

  7. Android Timer的使用

    1:服务端使用PHP <?php echo date('Y-m-d H:i:s'); ?> 2:activity_main.xml <RelativeLayout xmlns:and ...

  8. android Handler更新UI

    android中经常需要更新界面某个元素的值,但是在主线程中是不可以直接更新主线程的值.这里推荐通过handler机制来更新值. 一Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主 ...

  9. ZYNQ. Interrupt(1)Private Timer

    Interrupt zynq的中断. The PS is based on ARM architecture, utilizing two Cortex-A9 processors(CPUs) and ...

随机推荐

  1. 安卓手机已保存WiFi密码查看助手(开源)

    一.需求分析 最近电脑需要连接WiFi,却发现WiFi密码给忘记了.而手机里有保存过的WiFi密码,但是在手机的设置界面看不到. 虽然已经有一些可以查看WiFi密码的app,但是主要还是担心密码被那些 ...

  2. python-数据类型补充及文件处理操作

    ___数据类型____ 一.列表的复制 浅复制和深复制 浅复制只复制一层,深复制完全克隆,慎用 1.实现浅复制的三种方式: name=['song','xiao','nan'] import copy ...

  3. 逗号分隔的字符串转换为行数据(collection)

    逗号分隔的字符串转换为行数据(collection) CREATE OR REPLACE FUNCTION "GET_STR_TAB" (v_str in varchar2) re ...

  4. MongoDB集群架构及搭建

    MongoDB分布式集群 MongDB分布式集群能够对数据进行备份,提高数据安全性,以及提高集群提高读写服务的能力和数据存储能力.主要通过副本集(replica)对数据进行备份,通过分片(shardi ...

  5. MySQL迁移[转]

    http://dbarobin.com/2015/09/15/migration-of-mysql-on-different-scenes/ MySQL 迁移方案概览 MySQL 迁移无非是围绕着数据 ...

  6. PAT 1018. 锤子剪刀布 (20)

    现给出两人的交锋记录,请统计双方的胜.平.负次数,并且给出双方分别出什么手势的胜算最大. 输入格式: 输入第1行给出正整数N(<=105),即双方交锋的次数.随后N行,每行给出一次交锋的信息,即 ...

  7. oracle 事务总结

    用了这么长时间的oracle,该总结一下所得了 1,事务 事务用于保证数据的一致性, 它由一组相关的 dml语句组成, 该组的dml(数据操作语言,增删改,没有查询)语句要么全部成功,要么全部失败,比 ...

  8. SQL Server 安装 功能详解

    安装 SQL Server 功能     在“功能选择”页上,SQL Server 功能分为以下两个主要部分:实例功能和共享功能. “实例功能”表示为每个实例安装一次的组件,这样,您将具有它们的多个副 ...

  9. android源码framework下添加新资源的方法

    编译带有资源的jar包,需要更改frameworks层,方法如下: 一.增加png类型的图片资源 1.将appupdate模块所有用到的png格式图片拷贝到framework/base/core/re ...

  10. Webwork 学习之路【07】文件上传下载

    Web上传和下载应该是很普遍的一个需求,无论是小型网站还是大并发访问的交易网站.WebWork 当然也提供了很友好的拦截器来实现对文件的上传,让我们可以专注与业务逻辑的设计和实现,在实现上传和下载时顺 ...