Android Handler

一、Android Handler介绍

Android Handler是一种事件驱动模型,用于实现线程切换或执行延时任务。它在整个Android开发体系中占据着很重要的地位,可以用于保证多个任务在执行时的有序性。在Android系统中,主线程有特殊地位,因此像EventBus和Retrofit这类并非Android独有的第三方库,都是通过Handler来实现对Android系统的特殊平台支持。

Android Handler的主要作用是将消息(Message)或Runnable对象发送到主线程的消息队列中,以便在主线程中执行。它可以通过post()方法将消息或Runnable对象发送到消息队列中,也可以通过sendMessage()方法将消息发送到消息队列中。当消息或Runnable对象被发送到消息队列中时,Handler会自动将它们封装成Message对象,并将它们添加到消息队列中。当主线程空闲时,Handler会从消息队列中取出消息或Runnable对象,并在主线程中执行它们。

以Handler的sendMessage方法为例,当发送一个消息后,会将此消息加入消息队列MessageQueue中。Looper负责去遍历消息队列并且将队列中的消息分发给对应的Handler进行处理。在Handler的handleMessage方法中处理该消息,这就完成了一个消息的发送和处理过程。

Handler机制的机制原理

Android中采用的是Linux中的管道通信,关于管道,简单来说,管道就是一个文件,在管道的两端,分别是两个打开文件文件描述符,这两个打开文件描述符都是对应同一个文件,其中一个是用来读的,别一个是用来写的。消息队列创建时,调用JNI函数,初始化NativeMessageQueue对象。NativeMessageQueue则会初始化Looper对象。Looper的作用就是,当Java层的消息队列中没有消息时,就使Android应用程序主线程进入等待状态,而当Java层的消息队列中来了新的消息后,就唤醒Android应用程序的主线程来处理这个消息。



Handler通过sendMessage()发送Message到MessageQueue队列。Looper通过loop(),不断提取出达到触发条件的Message,并将Message交给target来处理。经过dispatchMessage()后,交回给Handler的handleMessage()来进行相应地处理。将Message加入MessageQueue时,处往管道写入字符,可以会唤醒loop线程;如果MessageQueue中- 没有Message,并处于Idle状态,则会执行IdelHandler接口中的方法,往往用于做一些清理性地工作。

管道,其本质是也是文件,但又和普通的文件会有所不同:管道缓冲区大小一般为1页,即4K字节。管道分为读端和写端,读端负责从管道拿数据,当数据为空时则阻塞;写端向管道写数据,当管道缓存区满时则阻塞。

在Handler机制中,Looper.loop方法会不断循环处理Message,其中消息的获取是通过 Message msg = queue.next(); 方法获取下一条消息。该方法中会调用nativePollOnce()方法,这便是一个native方法,再通过JNI调用进入Native层,在Native层的代码中便采用了管道机制。

我们知道线程之间内存共享,通过Handler通信,消息池的内容并不需要从一个线程拷贝到另一个线程,因为两线程可使用的内存时同一个区域,都有权直接访问,当然也存在线程私有区域ThreadLocal(这里不涉及)。即然不需要拷贝内存,那管道是何作用呢?

Handler机制中管道作用就是当一个线程A准备好Message,并放入消息池,这时需要通知另一个线程B去处理这个消息。线程A向管道的写端写入数据1(对于老的Android版本是写入字符W),管道有数据便会唤醒线程B去处理消息。管道主要工作是用于通知另一个线程的,这便是最核心的作用。

为什么采用管道而非Binder?

从内存角度:通信过程中Binder还涉及一次内存拷贝,handler机制中的Message根本不需要拷贝,本身就是在同一个内存。Handler需要的仅仅是告诉另一个线程数据有了。

从CPU角度,为了Binder通信底层驱动还需要为何一个binder线程池,每次通信涉及binder线程的创建和内存分配等比较浪费CPU资源。

Handler与MessageQueue、Message、Looper直之间的关系

Handler是用于线程间的通信,它可以将消息(Message)发生到MessageQueue中,然后在指定的线程中接收并处理这些消息。

MessageQueue是用于储存消息的队列,每个线程都有一个MessageQueue,用于存储等待处理的消息。

Message用于在线程之间传递消息,它包含了一些需要传递的信息以及Handler对象。

Looper是用于循环读取MessageQueue中的消息并将它们交给Handler来处理的对象,它只能存在一个线程中,通常是主线程。

Message是承载任务的载体,在Handler机制中贯穿始终,Handler则是对外公开的API,负责发送Message和处理任务的回调,是Message的生产者,Message负责管理待处理Message的入队和出队,是Messae的容器,Looper负责轮循MessageQueue,保持线程持续运行任务,是Message的消费者。

因此,当我们在一个线程中使用了Handler,他会向该线程的MessageQueue中发生消息,然后由Looper在该线程中循环读取该MessageQueue中的消息,并将消息交给Handler来处理。这些机制使得我们可以很方便地实现线程间得通信和操作UI等操

作。 Handler 的背后有着 Looper 以及 MessageQueue 的协助,三者通力合作,分工明确。

Looper :负责关联线程以及消息的分发在该线程下从 MessageQueue 获取 Message,分发给Handler ;

MessageQueue :是个队列,负责消息的存储与管理,负责管理由 Handler 发送过来的Message;

Handler : 负责发送并处理消息,面向开发者,提供 API,并隐藏背后实现的细节。

Handler 发送的消息由 MessageQueue 存储管理,并由 Loopler 负责回调消息到 handleMessage()。

线程的转换由 Looper 完成,handleMessage() 所在线程由 Looper.loop() 调用者所在线程决

二、Android Handler相关类

JAVA类

Handler

Handler类是Android中的一个类,它主要用于在不同的线程之间传递和处理消息。它可以将消息和Runnable对象安排到Messag

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值