handler消息处理机制

handler什么?

​ Handler一个消息处理机制负责发送处理消息的类,是消息处理的关键。

消息处理涉及的主要类

消息处理的基本原理

在这里插入图片描述

Thread、Handler、Lopper、MessageQueue对应关系

一个Lopper对应一个MessageQueue,因为Looper内置了一个消息队列

​ 一个Thread只能有一个Lopper

​ 一个Handler对象对应一个Thread和Thread的消息队列(但是一个Thread可以多个Handler)。当你创建一个Handler时,它就和Thread的消息队列绑定在一起。

特别注意:Handler虽然和Looper是一一对应的,但是Hanlder本身并不含有Looper,Looper通过线程内部存储存储在Thread里的的,而Looper内置了一个消息队列

消息传递基本思想

​ 在线程B中获取属于线程A的handler,在B中创建message可以通过调用handler.sendmessagemessage对象)将消息添加到A线程的消息队列中去,A线程的Looper循环取出消息并通知hanlder去处理消息,调用回调函数handler.handleMessage(用户一般要重写方法)去处理消息。所以就实现了把B线程的数据封装message传递给线程A,通过线程A中重写handlerhandleMessage方法在线程A中处理消息。

handler消息处理机制能做什么

Handler

​ Handler用于发送、处理消息,Handler本身不含有message,而message有个target属性hanlder类型),用于此条标识消息要由哪个handler去处理。

​ Handler有多个构造函数,但本质上都是外部传入一个Looper,Handler属于哪个现场取决于传入Looper属于哪个线程。

post(runable)				//发送消息,Runnable是消息回调,经过消息循环引发消息回调函数执行
    
sendMessage(message)		//发送消息,经过消息循环派发消息处理函数中处理消息;

dispatchMessage(messsage)   //派发消息,主要作用就是根据情况调用回调函数
                     //若是post或带有回调函数执行回调函数,否则执行消息处理函数Handler的handleMessage(通常派生类写)。

sendMessage和post两种发消息的本质是一样的,都是发送一个Message。只是post(runable r)方法发送的是一个callback属性为r的message,两个方法发出的消息在loop取出后,最终都会交到dispatchMessage处理。

handler消息处理的流程图

在这里插入图片描述

dispatchMessage(派发消息)源码分析

​ 从代码可以看到message本身有一Runable接口,只有它为空执行handlemessage。

​ hanlder本身包含一个回调函数handlemessage,它本身又包含一个callback接口接口里面又是一个handkemessage回调函数,到底执行哪个handlemessage就在dispatchMessage中判断判断优先级是:消息回调 > handler的callback的回调 > handler本身回调

    public void dispatchMessage(@NonNull Message msg) {
        if (msg.callback != null) {		//首先判断消息本身Runable是否为空,不为空就只执行消息的callback(Runable类型
            handleCallback(msg);
        } else {
            if (mCallback != null) {	//如果handler的callback接口为空,则执行hanlder的callback的回调函数
                if (mCallback.handleMessage(msg)) {	
                    return;				//再如果callback的回调函数中true,则不执行hanlder本身的回调函数
                }
            }
            handleMessage(msg);			//当消息的callback为空且handler的callback为空或者,才执行handler本身的回调函										数
        }
    }

Looper

实现Thread的消息循环和消息派发,缺省情况下Thread没有这个消息循环的,即没有Looper;

需要主动去创建调用Lopper.prepare()),然后启动消息循环(调用Lopper.loop());与外部交互通过Handler进行;

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

拓展 —ThreadLocal

​ ThreadLoacal是Thread中内置的存储类,其本身并不存储数据,而是通过它内置的ThreadLoacaMap来存储数据的。

其主要方法有:

在不同线程中执行get方法得到的值是不同的,得到的值是在对应线程set的值

Message

public final class Message implements Parcelable {
    //标识消息
    public int what;
    int flags;
    long when;
    //传递简单数据
      public int arg1;
    public int arg2;
    //传递复杂数据 对象
    public Object obj;
    Bundle data;
    //处理消息的目标Handler
    Handler target;   
    //消息派发时 执行的Runnable对象
    Runnable callback;  
    //使消息形成链表
    Message next;
    //建立一个消息pool回收msg,以避免重复创建节约开销
    private static Message sPool;
    private static int sPoolSize = 0;
    private static final int MAX_POOL_SIZE = 10;
  }  

​ Message提供了obtain方法:通过obtain获取,可从MessagePool中获取(MessagePool类似数据库连接池)一个消息,可以节约开销。也通过myhanlder.obtain(),来获取一条targetmyhanlder的对象的message。每条消息都有一个target,在某个handler发送消息(sendpost)时,最终会将该handler赋值给该message.target以便于在消息队列取出消息后直调用消息的target去处理消息。

MessagePool

可以将创建的对象用完之后回收以便重复利用节约频繁创建释放开销。

public static void loop() {
       while (true) {
  //派发消息
  msg.target.dispatchMessage(msg);

  //消息处理完毕 回收
        msg.recycle();
    }
}     

public void recycle() {
       //回收Message 建立全局的MessagePool
       if (sPoolSize < MAX_POOL_SIZE) {
           next = sPool;
           sPool = this;
           sPoolSize++;
       }
}

原文地址:https://blog.csdn.net/qq_43800449/article/details/130447487

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_26212.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注