Android之handler消息处理机制详解

handler消息处理机制

handler是什么?

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

消息处理涉及的主要类

  • Handler:负责发送消息和处理消息
  • Looper:内置一个死循环,可以不断的取出消息并通知handler处理消息,是handler起作用的基础
  • Message:消息实体类
  • MessageQueue:消息队列,负责存储消息

消息处理的基本原理

在这里插入图片描述

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.sendmessage(message对象)将消息添加到A线程的消息队列中去,A线程的Looper循环会取出消息并通知hanlder去处理消息,调用回调函数handler.handleMessage(用户一般要重写此方法)去处理消息。所以就实现了把B线程的数据封装到message中传递给线程A,通过线程A中重写handler的handleMessage方法在线程A中处理消息。

handler消息处理机制能做什么?

  • 实现消息的异步处理,例如将子线程的数据通过Message传递到主线程中
  • 一般来说UI控件只能在主线程中更新,但是在子线程中可以通过handler更新UI

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进行;

  • Lopper.prepare() //为当前线程创建Lopper对象,实质上是new一个Looper然后通过当前线程内置的存储类ThreadLoacl保存该Looper,由于每个线程只能有一个Looper,所以通过prepare()创建Looper每次会判断当前线程是否有Looper,有则异常。在这里插入图片描述
  • Looper.loop() //通过死循环来不断取出当前线程Looper的消息队列中的消息,消息队列没有数据了就会挂起,核心代码如下图

在这里插入图片描述

  • Looper.myLooper()//获取当前线程的Looper对象,底层是通过当前线程内置的线程存储类ThreadLoacl.get()来获得,获得的内容在Looper执行prepare()时通过ThreadLoacl.set()传入的Looper对象。

在这里插入图片描述

在这里插入图片描述

  • Looper.myQueue()//获取Looper对应的消息队列
  • Looper.getMainLooper()//获取主线程的Looper对象

拓展 —ThreadLocal

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

其主要方法有:

  • set(T t) //设置线程变量
  • get() //获得线程变量,调用前一定要调用set方法否则报空指针异常

在不同线程中执行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(),来获取一条target是myhanlder的对象的message。每条消息都有一个target,在某个handler发送消息(send或post)时,最终会将该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++;
       }
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Android中的Handler是一种消息处理机,它可以用来处理线程之间的通信。当一个线程需要向另一个线程发送消息时,可以通过Handler消息发送到目标线程的消息队列中,目标线程再从消息队列中取出消息进行处理。通过Handler,我们可以实现线程之间的通信和协作,从而提高应用程序的性能和响应速度。 ### 回答2: Android中的Handler是一个非常重要的概念,它可以用于处理线程间的通讯以及异步任务的处理。本文将详细介绍AndroidHandler的概念及如何使用Handler处理消息。 一、Hanlder概念 HandlerAndroid的一个消息处理机,通过它我们可以传递和处理消息。它通常与MessageQueue和Looper一起使用,MessageQueue用来存放消息,Looper用来处理MessageQueue中的消息Handler则是用来发送和处理消息的,它是与Looper绑定在一起的,可以在任何线程中创建,用来发送消息到绑定的Looper所在的线程中。 二、Handler使用 1. Handler的创建 Handler的创建可以在主线程中,也可以在子线程中。在主线程中,系统已经创建了主线程的Looper,可以直接使用,无需再创建。在子线程中,需要先创建Looper,然后再创建Handler。 2. Handler的发送消息 使用Handler发送消息的方式有三种:post(Runnable r)、sendMessage(Message msg)和sendEmptyMessage(int what)。 post(Runnable r):表示在Handler所在线程的消息队列中插入一个Runnable对象,这个Runnable对象可以是任何实现了Runnable接口的类。 sendMessage(Message msg):表示向Handler所在线程的消息队列中插入一个Message对象,可以在Message对象中携带自定义数据。 sendEmptyMessage(int what):表示向Handler所在线程的消息队列中插入一个Message对象,这个Message对象里面不携带任何数据。 3. Handler的处理消息 如果需要对发送的消息进行处理,则必须重写Handler的handleMessage(Message msg)方法,并在该方法中对不同类型的消息进行处理。 三、常见问题 1. Handler引起的内存泄漏 由于Handler在处理消息时会持有外部对象的引用,如果这个外部对象被销毁了,但Handler没有被销毁,就可能造成内存泄漏。解决方法是使用静态内部类或弱引用方式创建Handler对象,使Handler对象与外部对象解耦,防止内存泄漏。 2. 跨线程通讯 Handler仅在发送消息和处理消息时是线程安全的,但必须要保证发送消息和处理消息的Looper在同一线程,否则会抛出异常。 3. 子线程中使用Handler 子线程中使用Handler需要先创建一个Looper,这个Looper必须在子线程中创建,否则会抛出异常。 四、总结 通过本文的介绍,我们了解了AndroidHandler的概念、使用和常见问题。HandlerAndroid中非常重要的一个消息处理机,可以用于处理线程间通讯和异步任务的处理。我们在使用Handler时必须注意内存泄漏问题,保证发送消息和处理消息的Looper在同一线程,同时在子线程中使用Handler需要先创建Looper。 ### 回答3: Android HandlerAndroid 系统中一个非常重要的消息处理机,它主要用于在子线程中更新 UI 界面,或者在不同的线程之间进行通信。在 Android 应用程序中,UI 界面和后台逻辑通常都在不同的线程中运行,如果直接在子线程中对 UI 进行更新,就会导致应用程序出现 ANR(Application Not Responding)异常。 因此,Android 系统提供了 Handler 消息处理机,通过 Handler,在不同的线程中进行通信,让子线程可以更新 UI 界面或者在主线程中执行任务,从而避免 ANR 异常的发生。 在使用 Handler 进行消息处理时,首先需要定义一个 Handler 对象,在这个对象中实现消息处理的方法,通常我们称之为 handleMessage() 方法。handleMessage() 方法会接收一个 Message 对象,该对象中包含了传递过来的数据和信息,我们可以在 handleMessage() 方法中对这些信息进行处理并更新 UI 界面。 当子线程需要向主线程发送消息时,可以通过 Handler 对象中的 sendMessage() 方法来发送消息,在主线程中通过 handleMessage() 方法来接收和处理这些消息。 另外,Handler 还支持定时发送和延时发送消息的功能,可以通过 postDelayed() 和 sendMessageDelayed() 方法来实现。这些方法可以让我们在需要的时候发送消息,并且可以延时执行或者定时执行。 需要注意的是,在使用 Handler 时,需要注意线程安全问题,如果在主线程中直接对 UI 进行更新,可能会出现线程安全问题,因此建议将消息发送到主线程中进行处理。 总之,Android Handler 消息处理机是实现异步消息通信和更新 UI 界面的非常重要的工具,它可以帮助开发者更好地进行线程间通信,避免 ANR 异常的发生,提高应用程序的稳定性和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值