android 接收通知流程,android Handler消息流程梳理

消息机制概述

Android 系统在设计的初期就已经考虑到了 UI 的更新问题,由于 Android 中的 View 是线程不安全的,然而程序中异步处理任务结束后更新 UI 元素也是必须的。这就造成了一个矛盾,最简单的解决方法肯定是给 View 加同步锁使其变成线程安全的。这样做不是不可以,只是会有两点坏处:

1 加锁会有导致效率底下

2 由于可以在多个地方更新 UI,开发就必须很小心操作,开发起来就很麻烦,一不小心就出错了。

基于以上两个缺点,这种方式被抛弃。于是,设置一个线程专门处理 UI控件的更新,如果其他线程也需要对 UI 进行更新,不好意思,您把您想做的告诉那个专门处理 UI 线程的家伙,让它帮你做。大家各有各的任务,井水不犯河水,各司其职,效率才会高,

那么您也看出来了,消息机制其实可以很简单的用一句话概括,就是:其他线程通过给特定线程发送消息,将某项专职的工作,交给这个特定的线程去做。比如说其他线程都把处理 UI 显示的工作通过发送消息交给 UI 线程去做。

消息机制相关类

消息主要设计到下面几个类:

Handler:这是消息的发出的地方,也是消息处理的地方。

Looper:这是检测消息的地方。

MessageQueue: 这是存放消息的地方,Handler 把消息发到了这里,Looper 从这里取出消息交给 Handler 进行处理

Message:呜呜呜…他们发的是我,处理的也是我。

Thread:我在这里专门指代的是,处理消息的线程。消息的发送是在别的线程。

源码跟踪--梳理消息发送接收过程

咱们先来走一个在子线程想要更新UI的流程:

1 在主线程新建一个 Handler 对象,在构造方法中传入一个实现 Handler.Callback 接口的匿名类的对象,实现接口中的 handleMessage 方法

2 在非 UI 线程使用 Handler 的 sendMessage 或者 post 方法发送一个消息

3 然后 handleMessage 方法会在不久的将来马上执行,实现更新 UI 的操作。

关于类Handler:

Handler 拥有 Looper 的引用,通过得到 Looper 对象获得 Looper 中保存的 MessageQueue 对象

Handler 拥有 MessageQueue 的引用,使 Handler 得以拥有发送消息(将 Message 放入 MessageQueue )的能力

Handler 拥有 Handler.Callback 的引用,使得 Handler 可以方便的进行消息的处理。

根据上面的1 2 3 步,我们跟进源码看看:

9cd351ac46a7

1 创建handler

9cd351ac46a7

handler构造方法源码

在handler中获取了mLooper,mQueue对象,主要看mLooper是怎么获取的,Looper.myLooper();再跟进这个方法:

9cd351ac46a7

Looper类

可以看到是由ThreadLocal维护的,我们知道ThreadLocal可以保存对应线程的变量,那么必定保存了当前线程的Looper。我们查找ThreadLocal.set()方法:

9cd351ac46a7

Looper类方法

可以看到是在调用Looper.prepare()时设置的,在主线程中是谁调用Looper.prepare()的呢?没错,就是ActivityThread(主线程),在创建主线程的main方法里调用:

9cd351ac46a7

ActivityThread中的main方法

那么就可以确定,上面ThreadLocal存储的Looper就是主线程的Looper。mQueue自然也是主线程的Looper的变量。然后就看发消息了,看看 Handler.sendMessage 干了啥,

9cd351ac46a7

handler类发送消息

可以看到,Handler类中发送消息最后调用了MessageQueue的enqueueMessage()方法,并且把msg.target设置成了handler本身,这在之后分析中用到,继续跟进:

9cd351ac46a7

MessageQueue类方法

到这里,我们发现handler已经成功法一个消息放到了主线程的MessageQueue中了,接下来就是取消息操作了。只要主线程中调用了Looper.loop()方法,那就启动了一个死循环,会从MessageQueue中不停的取消息(无消息就阻塞)。

9cd351ac46a7

Looper的loop方法

可以看到,loop()方法开启了一个死循环,不断从MessageQueue取消息,并调用msg.target(Handler)去调用dispatchMessage(msg)方法。那就是调用了handler的dispatchMessage(msg)方法

9cd351ac46a7

handler类方法

这里分三种情况,

* 如果Message中callback对象不为空(这是调用handler.post(Runnable)方法发送的消息),就调用callback的run方法

* 否则如果创建Handler的时候如果设置了Callback就调用创建时候的传入的实现Handler.Callback接口的类的对象的handleMessage方法,看这就是回调方法被调用的地方。

* 再如果没有mCallback对象,就调用自身的handleMessage方法,为了Handler的子类复写了该方法的时候,方便调用,如,IntentService里的ServiceHandler就是继承自Handler的,并且重写了handleMessage方法。

我们创建handler时实现了Handler.Callback接口,所以就跳到一开始创建handler的地方处理消息啦。

小结

ok,再整理一下思路:1 在主线程创建handler实现Handler.Callback接口,主线程一运行就存在Loop和MessageQueue。2 其他线程通过主线程的该handler发送msg,发送到了主线程的MessageQueue。3 主线程的Looper从MessageQueue循环取消息,取到该消息就调用msg.target(handler).dispatchMessage(msg),也就跟着调用了handler的handleMessage()。

另外,如果非主线程要创建handler对象,必须要调用Looper.prepare()创建一个Looper和Looper.loop()开启消息循环。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答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 异常的发生,提高应用程序的稳定性和用户体验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值