Android中使用Timer时需要同时访问TimerTask,Handle等类,手续繁杂而且是真正想做的事淹没在手续化的代码中。本文介绍了的SafetyTimer类隐藏了TimerTask,Handle等类,并通过Observer设计模式为用户提供简单,低耦合的实现方式。

首先看一下SafetyTimer在整个软件中的位置。

有点偏,不过没有关系。

让我们开始。

关于Android定时器的使用,网上有很多例子。一般来讲是这样的。

        
  1. publicclassTestTimerextendsActivity{
  2. Timertimer=newTimer();
  3. Handlerhandler=newHandler(){
  4. publicvoidhandleMessage(Messagemsg){
  5. switch(msg.what){
  6. case1:
  7. setTitle("hearme?");//这里才是要做的事情。
  8. break;
  9. }
  10. super.handleMessage(msg);
  11. }
  12. };
  13. TimerTasktask=newTimerTask(){
  14. publicvoidrun(){
  15. Messagemessage=newMessage();
  16. message.what=1;
  17. handler.sendMessage(message);
  18. }
  19. };
  20. publicvoidonCreate(BundlesavedInstanceState){
  21. super.onCreate(savedInstanceState);
  22. setContentView(R.layout.main);
  23. timer.schedule(task,10000);//启动定时器
  24. }
  25. }

之所以要这么麻烦的原因是TimerTask的run方法是在一个独立的Task里执行的,和我们的用用不在一个上下文中,所以不能直接在TimerTask的run方法中执行我们希望定期执行的代码。

作为解决这个问题的方案之一,引入了Handler类,先由TimerTask调用Handler.sendMessage(多任务安全)向Handler发消息(在这个地方,其实什么消息都可以),Android先可以保证,等到Handler.handleMessage的时候,就已经是和应用在同一个上下文里了。

以下是参考资料 Timer: http://developer.android.com/reference/java/util/Timer.html TimerTask: http://developer.android.com/reference/java/util/TimerTask.html Handler: http://developer.android.com/reference/android/os/Handler.html

看起来挺累的吧,要找到我们真正想做的事还真是不容易。但是又不得不看。有没有办法把这件事弄的漂亮一点呢,有。

方法1:利用类的继承

首先写一个如下的基类,基本上例子中的代码相同,只是在定义了一个没有内容的OnTimer方法留给派生类实现。

        
  1. publicclassTemplateMethodTimer{
  2. privateTimermTimer=null;
  3. privateHandlermHandler=null;
  4. privateTimerTaskmTask=null;
  5. //TemplateMethod接口定义,具体动作有派生类时装。
  6. publicvoidOnTimer(){
  7. }
  8. //启动定时器
  9. publicvoidstartTimer(longinterval){
  10. mHandler=newHandler(){
  11. publicvoidhandleMessage(Messagemsg){
  12. OnTimer();//调用模板方法。
  13. super.handleMessage(msg);
  14. }
  15. };
  16. mTask=newTimerTask(){
  17. publicvoidrun(){
  18. Messagemessage=newMessage();
  19. message.what=0;//anythingisok.
  20. mHandler.sendMessage(message);
  21. }
  22. };
  23. mTimer=newTimer();
  24. mTimer.schedule(mTask,0,interval);
  25. }
  26. //停止Timer动作
  27. //释放获得的资源。
  28. publicvoidstopTimer(){
  29. mTimer.cancel();
  30. mTimer.purge();
  31. mTimer=null;
  32. mHandler=null;
  33. mTask=null;
  34. }
  35. }

有了这个类我们就可以相下面这样先定义一个派生类并提供OnTimer方法的实现。

        
  1. classMyTimerextendsTemplateMethodTimer{
  2. publicvoidOnTimer(){
  3. Log.i(TAG,"MyTimer.OnTimer");
  4. }
  5. }

然后创建一个定时器并进行启动停止操作

        
  1. MyTimermMt=newMyTimer();
  2. mMt.startTimer(500);
  3. mMt.stopTimer();

当然在JAVA中我们可以向下面这样创建Timer

        
  1. TemplateMethodTimermTt=newTemplateMethodTimer(){
  2. publicvoidOnTimer(){
  3. Log.i(TAG,"TestTimer.OnTimer");
  4. }
  5. };

本质上是一样的代码。

方法2:利用类的Observer设计模式,这时Timer类是这样的。

        
  1. publicclassObserverTimer{
  2. privateTimermTimer=null;
  3. privateHandlermHandler=null;
  4. privateTimerTaskmTask=null;
  5. privateOnTimeListenermListener=null;
  6. privatestaticfinalStringTAG=newString("SafetyTimer");
  7. //Observer接口定义
  8. publicinterfaceOnTimeListener{
  9. publicvoidOnTimer();
  10. }
  11. //创建定时器并指定Observer
  12. publicvoidsetListener(OnTimeListenerlistener){
  13. mListener=listener;
  14. }
  15. //启动定时器
  16. publicvoidstartTimer(intinterval){
  17. mHandler=newHandler(){
  18. publicvoidhandleMessage(Messagemsg){
  19. if(mListener!=null){
  20. mListener.OnTimer();
  21. Log.i(TAG,"mListener.OnTimer()");
  22. }
  23. super.handleMessage(msg);
  24. }
  25. };
  26. mTask=newTimerTask(){
  27. publicvoidrun(){
  28. Messagemessage=newMessage();
  29. message.what=0;//anythingisok.
  30. mHandler.sendMessage(message);
  31. }
  32. };
  33. mTimer=newTimer();
  34. mTimer.schedule(mTask,0,interval);
  35. }
  36. //停止Timer动作
  37. //释放获得的资源。
  38. publicvoidstopTimer(){
  39. mTimer.cancel();
  40. mTimer.purge();
  41. mTimer=null;
  42. mHandler=null;
  43. mTask=null;
  44. Log.i(TAG,"stopTimer()");
  45. }
  46. }

这段代码与方法一的不同点在于。

1.没有定义供覆盖的方法但是定义了一个OnTimerListener类。 2.增加了OnTimerListener类型的数据成员mListener并提供设定它的接口。 3.在Handler的消息处理中没有调用自己的方法(也没有)而是调用设定好的mListener.OnTimer() 有了这个ObserverTimer类,我们就可以像下面这样创建和使用Timer了。
        
  1. ObserverTimermOt=newObserverTimer();
  2. mOt.setListener(new ObserverTimer.OnTimeListener() {
    @Override
    public void OnTimer() {
    Log.i(TAG, "ObserverTimer.OnTimer");
    }
    });
  3. mOt.startTimer(1000);
  4. mOt.stopTimer();

是不是好多了。这样的代码在Android里到处都是,关键是我们自己做的代码会不会做成这样的。

用法好像区别不大,那么哪个个方法更好些呢?

方法1是定义了,一个不知道自己应该干什么的基类,然后通过派生类实现做某某事的Timer。抽象的是Timer。

方法2是定义的一个专门响应Timer的Listener基类,通过Listener的派生类实现具体的功能工作。抽象的要做的事,应该说更接近本质吧。即使是从功利的角度来看也可以看出Listener是可以动态登录和删除,比较灵活。当然更不用说如果对Obersever稍加改造,可以实现多个对象响应Timer事件了。

不言自明了吧。

通过本文,我们可以看到通过Observer设计模式封装,隐藏复杂的Timer处理的方法。这样下一个再用Timer的人,就不必再走一次别人已经走过的路而把节约下来的时间用在其他需要挑战的地方。这样做其实没有什么难度,但是实际工作中会这么做的恐怕还真就不多。无论如何请相信:这看似不大的一步,会从根本上改变我们的程序结构的。

在Android歌词秀(http://craftsman1970.blog.51cto.com/3522772/659482)中用到的SaftyTimer类,就是用方法二实现的,供参考。

我们通过SaftyTimer封装了灰色的Timer,TimerTask,Handler的功能然后通过定义SaftyTimer:OnTimeListener为利用者提供实现所需功能的途径。

下面是时序图

从图中可以很清楚的看到从LayerPlayerService出发的调用中除了生成新对象的2条线以外,只有StartTimer,OnTimer,StopTimer三条线。而SaftyTimer右侧的调用则相对会复杂很多。这就是封装的效果。

以下是源代码,整个工程文件源码下载:http://down.51cto.com/data/249418

        
  1. packageLyricPlayer.xwg;
  2. importjava.util.Timer;
  3. importjava.util.TimerTask;
  4. importandroid.os.Handler;
  5. importandroid.os.Message;
  6. importandroid.util.Log;
  7. publicclassSafetyTimer{
  8. privateTimermTimer=null;
  9. privateHandlermHandler=null;
  10. privateTimerTaskmTask=null;
  11. privateOnTimeListenermListener=null;
  12. privatelongmInterval=0;//inmilliseconds
  13. privatestaticfinalStringTAG=newString("SafetyTimer");
  14. //Observer接口定义
  15. publicinterfaceOnTimeListener{
  16. publicvoidOnTimer();
  17. }
  18. //创建定时器并指定Observer
  19. publicSafetyTimer(longinterval,OnTimeListenerlistener){
  20. mInterval=interval;
  21. mListener=listener;
  22. }
  23. //启动定时器
  24. publicvoidstartTimer(){
  25. mHandler=newHandler(){
  26. publicvoidhandleMessage(Messagemsg){
  27. if(mListener!=null){
  28. mListener.OnTimer();
  29. Log.i(TAG,"mListener.OnTimer()");
  30. }
  31. super.handleMessage(msg);
  32. }
  33. };
  34. mTask=newTimerTask(){
  35. publicvoidrun(){
  36. Messagemessage=newMessage();
  37. message.what=0;//anythingisok.
  38. mHandler.sendMessage(message);
  39. }
  40. };
  41. mTimer=newTimer();
  42. mTimer.schedule(mTask,0,mInterval);
  43. }
  44. //停止Timer动作
  45. //释放获得的资源。
  46. publicvoidstopTimer(){
  47. mTimer.cancel();
  48. mTimer.purge();
  49. mTimer=null;
  50. mHandler=null;
  51. mTask=null;
  52. Log.i(TAG,"stopTimer()");
  53. }
  54. //Timer是否处于工作状态。
  55. publicbooleanisRunging(){
  56. return(mTimer!=null);
  57. }
  58. }
本文出自: http://craftsman1970.blog.51cto.com/3522772/659906

更多相关文章

  1. 保存/恢复Activity和Fragment状态的最佳实践(译)
  2. android 最简单的自定义适配器(BaseAdapter+ListView)
  3. Android(安卓)View构造方法第三参数使用方法详解
  4. android 霓虹灯效果
  5. Android中定时执行任务的3种实现方法
  6. 《第一行代码:Android(第2版)》,作者郭霖
  7. Android(安卓)WebView那些坑之上传文件
  8. Android(安卓)进阶 教你打造 Android(安卓)中的 IOC 框架 【View
  9. 条件数据库Android:sqllite使用

随机推荐

  1. 看Google官方的Android开发文档的一些收
  2. Android超实用的Toast提示框优化分享
  3. Android中几种图像特效处理的集锦
  4. Android编译环境
  5. Android中文程序员向导教材目录
  6. Android动态壁纸的制作教程
  7. afinal的简单应用(一)
  8. Android之GridView简单说明
  9. Android(安卓)ListView中点击单行实现Rad
  10. 《Android学习大纪事之--属性动画ObjectA