在我们Android开发过程中,经常需要执行一些短周期的定时任务,这时候有两个选择Timer或者Handler。然而个人认为: Handler 在多个方面比Timer更为优秀,更推荐使用。
若想要执行一个越来越快的定时任务,Handler可以做到,而Timer则消耗较大。
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比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的测试结果。
共有5个对象,占用1192B。
我们可以看到上面有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更胜一筹.