美文网首页
图文并茂深入浅出地话你知,Android的Handler究竟是怎

图文并茂深入浅出地话你知,Android的Handler究竟是怎

作者: 深图 | 来源:发表于2018-05-19 00:04 被阅读0次

    1.前言

    网络上关于Handler的介绍已经有太多了,

    本文希望能图文并茂简单地介绍一下Handler,让大家更形象地理解并掌握Handler。

    2.Handler是什么?

    简单地说,Handler是 用来响应和处理消息的工具,所以才叫“Handler”。

    例如,如果你想处理别人给你发的消息,通过Handler提供的方法填写你的响应代码就可以实现。

    3.Handler都能干些什么?

    通过Handler能干的事情:

    1.让程序能响应消息;

    2.让程序能发送消息;

    3.让程序能删除消息;

    为了让程序员用起来方便,体验爽快,在发送消息和响应消息上,有想方设法换不同花样进行封装接口。

    例如:

    1.发送的消息可以指定什么时间才被处理,比如sendMessageAtTime;

    2.响应应消息的时候不关心消息值,只想随手写段代码等一下就能自动被调用,比如post(Runnable)。

    3.1 响应消息

    为了让程序员便捷地开发响应消息的代码,Handler提供了以下方式来响应消息:

    给Handler对象指定一个callback函数;

    派生Handler类,重载Handler的handleMessage()函数;

    给具体的消息捆绑一个callback;

    参考下面的“消息响应示意图”:


    消息响应示意图

    上图中,“消息处理代码1”就是第1中方式中对应callback函数体,所有“Handler丙”对应的消息被处理的时候都会调用“消息处理代码1”。

    “消息处理代码2”就是第2中方式中对应的handleMessage()函数体,所有“Handler甲”的消息被处理的时候都会调用“消息处理代码2”。

    “消息处理代码3”就是第3中方式中对应的callback响应函数体,只有“消息乙2”被处理的时候才会调用“消息处理代码3”(其实这个callback在实际编码中,形式是一个Runnable类实例,这个后面有介绍)。

    为了更好地让大家了解以上方式的差异,接下来对这几种响应方式配合代码介绍一下。

    3.1.1 给Handler对象指定一个callback函数

    通过在指定的callback函数内编写响应消息的代码来处理消息,例如在构造函数提供一个callback,参考源码:

    public class MyMessageCallback implements  Handler.Callback // 自定义一个callback  
    { 
    public boolean handleMessage(Message msg)  
        {  
    switch (msg.what)  
            {  
    case EVENT_WIN_INIT:  
      do something  
    break;  
            }  
    return false;  
        }  
    }  
    Handler myMessageHandler =new Handler(new MyMessageCallback()); // 构造时候提供自定义的callback实例  
    

    从以上源码中可以看出,在构造的时候通过传入MyMessageCallback对象实例的方式来响应和处理消息。

    3.1.2 派生Handler类,重载Handler的handleMessage()函数

    通过在子类的handleMessage()函数内部编写响应消息的代码来处理消息,参考源码:

    public class MyHandler extends Handler
        {
            public void handleMessage(Message msg) // 重载处理消息的函数
            {
                switch (msg.what){
                    case EVENT_WIN_INIT:
                        do something...
                        break;
                }
            }
        }
    

    从以上源码中可以看出,只需重载andleMessage()函数即可达到响应和处理消息的目标。对应以上代码,如果你想让它响应EVENT_WIN_INIT消息,那么你只需这样就行:

    MyHandler handler = new MyHandler();
    handler.sendEmptyMessage(EVENT_WIN_INIT);
    

    3.1.3 给具体的消息捆绑一个callback

    在发送具体某个消息的时候指定一个callback,待到消息被排队到处理的时候,将调用指定的callback。

    这种方式的callback稍微有点特殊,通过程序提供一个Runnable对象实例来实现。例如post(myRunnable);

    参考源码:

    public class MyMessageCallback implements Runnable
        {
            public void run()
            {
                do something...
            }
        }
    
        MyMessageCallback myMessageCallback = new MyMessageCallback();
        handler.post(myMessageCallback);
    

    以上代码,handler.post(myMessageCallback)调用后会在消息队列插入一个新消息,
    这个新消息被处理的时候将会调用MyMessageCallback下的run函数。

    3.2 发送消息

    想要响应消息,必须有人使用Handler对象给你发送消息,
    发送消息的本质,就是通过Handler对象往消息队列中插入消息。
    参考插入消息示意图:


    插入消息示意图

    注意很重要的一点,别人给你发送消息用的handler对象必须和你用来响应消息的handler对象是同一个!
    例如在“消息响应示意图”中,如果想在“Handler甲”里面响应消息,那么发送消息时候,必须使用“Handler甲”进行发送消息。
    Handler中发送消息分为post和send两种,例如post(Runnable)、sendMessage(msg)。其实post和send本质上没有什么差异,仅仅是编码上的形式差异而已,通过不同的封装,让程序员在不同需求场合更为灵活和便捷地编写响应代码。
    其中,post的方式一般是自己给自己发送消息,例如自己有段代码想过一会再执行,可以post的方式便捷地编写代码实现,参考下面代码:

    Handler handler = new Handler();
    handler.post(new Runnable()
    {
        @Override
        public void run()
        {
            // "do something"
        }
    });
    

    Handler发送消息的各个函数就不在此罗嗦,有需要的请查阅相关代码和资料。

    3.3 移除消息

    既然有插入消息,肯定有时候会遇到移除消息的情景。所以Handler也提供了从消息队列移除消息的功能函数,例如removeMessages()。
    参考移除消息示意图:


    移除消息示意图

    注意,移除消息仅针对某个handler对象的,例如“Handler甲”只能移除自己插入的消息,不能移除“Handler乙”所插入的消息。

    4.Handler和线程通信

    本文前面就提到,Handler是 用来响应和处理消息的工具,这个说法其实是过于简略,因为文章刚开始并不想让大家牵涉太复杂的细节。
    实际上,Handler的设计更重要的一个目的是让程序能简单地实现线程间通信。所以呢,Handler除了可以用来响应本线程的消息,也能响应其它线程发送过来的消息。
    参考下面的“线程通过Handler通信示意图”:

    线程通过Handler通信示意图
    图中,线程2通过访问“Handler甲”对象,发消息给线程1,
    线程1收到消息处理的时候实际运行的代码“Handler甲”中的“消息处理代码”,
    这段代码的运行实在线程1中发生的,如此,达到了线程2发消息给线程1的目的。
    大概说起来就这么简单,实际操作编码的时候,要注意的两点:
    *线程2如何能访问“Handler甲”对象
    *“Handler甲”对象如何保证能在线程1中运行
    规则:Handler关联哪个线程的消息队列,那么响应时候的处理代码就运行在对应的那个线程。
    所以,为了保证“Handler甲”对象能在线程1中运行,“Handler甲”必须关联线程1的消息队列。

    Handler怎么关联消息队列?

    Handler对象关联消息队列的两种方法:
    1.创建的时候自动关联所在线程的消息队列;
    2.创建的时候指定某个线程的消息队列;
    第1种方法,参考下面的代码,在线程1的运行代码中创建“Handler甲”,构造函数不传参数则自动关联线程1的消息队列:

    final Thread thread1 = new Thread(new Runnable()  
            {  
                @Override  
                public void run()  
                {  
                    createMessageQueue(); //伪代码:创建线程的消息队列...  
      
                    // 在线程1中创建Handler甲,使得Handler甲操作的消息队列属于线程1的
                    Handler甲 = new Handler()
                    {  
                        public void handleMessage(Message msg)  
                        {  
                            if (msg.what == EVENT_JUST_FOR_TEST) {  
                                do something....  
                            }  
                        }  
                    };  
                }  
            });  
            thread1.start();  
    

    从上面的代码可以看到,通过在线程1中“new Handler()”的方式创建了“Handler甲”,这样会自动和本线程的消息队列关联上,也就是“Handler甲”的操作都是针对线程1的消息队列。至于线程1的消息队列怎么来的,大家先别管,本文只介绍Handler。

    第2种方法,创建Handler的时候必须指定线程1的消息循环进行关联,例如我们在线程2运行体内创建:

    inal Thread thread2 = new Thread(new Runnable()  
           {  
               @Override  
               public void run()  
               {  
                   Handler甲 = new Handler(<strong>thread1.getlooper()</strong>)  
                   {  
                       @Override  
                       public void handleMessage(Message msg)  
                       {  
                           if (msg.what == EVENT_JUST_FOR_TEST) {  
                               this.getLooper().quit();  
                           }  
                           super.handleMessage(msg);  
                       }  
                   };  
    

    以上代码,虽然我们线程2运行体内创建了“Handler甲”,但是“Hanlder甲”关联的线程1的消息队列,所以“Handler甲”的消息被处理的时候,实际上是在线程1中运行的。

    结尾

    Handler暂时介绍这么多,为了更好地理解Handler的作用,大家还需要对Looper、MessageQueue进行了解。

    本文同时发布于:https://blog.csdn.net/henysugar/article/details/80271388

    相关文章

      网友评论

          本文标题:图文并茂深入浅出地话你知,Android的Handler究竟是怎

          本文链接:https://www.haomeiwen.com/subject/ogondftx.html