字节跳动面试官:Android-中为什么需要-Handler-

这里以用户滑动微信朋友圈为例,讲解一下 Android 的 Message 机制是怎么运行的,Message 机制中的各个核心组件都做了什么

Message 产生

用户滑动屏幕,产生了一系列 input 事件 (一个 Down 事件,若干个 Move 事件,一个 Up 事件),这些事件被系统包装成了一系列 Message(一个 Down Message,若干个 Move Message,一个 Up Message)

Message 是用来传递信息的,上述 Message 中就包含了这些 input 事件的信息,比如 x 坐标,y 坐标。

MessageQueue 存放 Message

Message 产生后,有一个问题就是这些 Message 怎么发给应用?我要滑动朋友圈,那么这些个 Message 就得传给微信,让微信去处理,微信将这些事件给到朋友圈的 List 控件,让 List 产生新内容,并且实现上下滑动。

首先想到的能不能直接把这些 Message 给到朋友圈的 List 控件(SystemServer 可以直接 Binder 发给 List 控件),可以是可以,但是麻烦;SystemServer 直接给朋友圈的 List 控件发 input message,那 SystemServer 得先知道有这么个控件,问题是应用有哪些控件,SystemServer 是不知道的,难道要遍历所有的控件,每个控件都发一个重复的 Message?这显然不是我们想要的。

SystemServer 不能直接发给控件,那么能不能直接发给应用,让应用自己去处理呢?答案是肯定的,现在的 Android 也是这么做的, 你应用准备一个 MessageQueue(消息队列),我有 Message 就放到这个 MessageQueue 里面,你应用自己去处理,岂不美哉,这就是 MessageQueue 出现的原因

Looper 派发 Message

应用准备了一个 MessageQueue 之后,SystemServer 把之前包装好的一系列 Input Message(一系列 Message(一个 Down Message,若干个 Move Message,一个 Up Message))放到了微信的 MessageQueue 里面,剩下的就让微信自己去读取 MessageQueue 里面的内容,自己更新 UI 去

问题是 MessageQueue 只是用来存放 Message 的,得有人来管理这个 MessageQueue。比如 MessageQueue 里面进了几个 Message,这些 Message 该到发给谁去处理?

这里就引入了 Looper,Looper 来决定这个 Message 该发给谁去处理,Looper 会按照 Message 在 MessageQueue 里面的顺序,一个一个取出 Message,根据 Message 自带的信息(我想被谁处理 - target),发给对应的人去处理

这个例子里面,这些 Message 的 target 就是微信的主线程的 handler

Handler 处理 Message

这时候,Handler 出场了,上面说 Looper 把 Message 发给对应的人去处理,这个就是 Handler。Handler 就是用来处理 Message 的,作为 Message 机制的最后一环,Handler 读取 Message 内容后,根据内容来做相关的处理。

这个例子里面,一系列 Input Message 最终会由微信的主线程 Handler 来处理,经过复杂的事件传递和事件分发流程,传给对应的 List 控件,List 控件根据 Input Message 里面的内容,计算出自己下一帧的各个 Item 的位置,更新自己的 Item 和 Item 内的内容,从而产生 List 滑动效果,朋友圈滑动的流程就完成了

Message 机制总结

有了上面的 Message 机制的案例,理解下面这张图就顺理成章了,如上面几个标题所示

  1. Message 承载内容
  2. MessageQueue 存放 Message
  3. Looper 派发 Message
  4. Handler 处理 Message

[图片上传失败…(image-7f2c84-1602639159720)]

Message 机制

App 主线程

那么,App 主线程是怎么回事?下面是 App 进程创建后,ActivityThread.main 方法被调用的逻辑

frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {

// 创建 Looper、Handler、MessageQueue
Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);

if (sMainThreadHandler == null) {
// 指定主线程的 handler 为 H
sMainThreadHandler = thread.getHandler();
}

// 开始准备接收消息
Looper.loop();
}
}

// 准备主线程的 Looper
frameworks/base/core/java/android/os/Looper.java
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException(“The main Looper has already been prepared.”);
}
sMainLooper = myLooper();
}
}

// prepare 方法中会创建一个 Looper 对象
frameworks/base/core/java/android/os/Looper.java
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException(“Only one Looper may be created per thread”);
}
sThreadLocal.set(new Looper(quitAllowed));
}

// Looper 对象创建的时候,同时创建一个 MessageQueue
frameworks/base/core/java/android/os/Looper.java
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}

通过上面的流程,主线程的 Looper、MessageQueue 都已经创建好了,这就打下了 Message 机制的基础,后续有 Message 进来,就会进入主线程的 MessageQueue ,然后 Looper 会把他派发给对应的 Handler

对于主线程来说,这个 Handler 就在 ActivityThread 里面,下面截取一小段 Handler 的方法,大家可以看一下,熟悉代码的应该知道,BIND_APPLICATION 就是大家经常在 Systrace 中看到的新进程启动时候的那一段

frameworks/base/core/java/android/app/ActivityThread.java
class H extends Handler {
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

《设计思想解读开源框架》

第一章、 热修复设计

  • 第一节、 AOT/JIT & dexopt 与 dex2oat

  • 第二节、 热修复设计之 CLASS_ISPREVERIFIED 问题

  • 第三节、热修复设计之热修复原理

  • 第四节、Tinker 的集成与使用(自动补丁包生成)

    第二章、 插件化框架设计

  • 第一节、 Class 文件与 Dex 文件的结构解读

  • 第二节、 Android 资源加载机制详解

  • 第三节、 四大组件调用原理

  • 第四节、 so 文件加载机制

  • 第五节、 Android 系统服务实现原理

    第三章、 组件化框架设计

  • 第一节、阿里巴巴开源路由框——ARouter 原理分析

  • 第二节、APT 编译时期自动生成代码&动态类加载

  • 第三节、 Java SPI 机制

  • 第四节、 AOP&IOC

  • 第五节、 手写组件化架构

    第四章、图片加载框架

  • 第一节、图片加载框架选型

  • 第二节、Glide 原理分析

  • 第三节、手写图片加载框架实战

    第五章、网络访问框架设计

  • 第一节、网络通信必备基础

  • 第二节、OkHttp 源码解读

  • 第三节、Retrofit 源码解析

    第六章、 RXJava 响应式编程框架设计

  • 第一节、链式调用

  • 第二节、 扩展的观察者模式

  • 第三节、事件变换设计

  • 第四节、Scheduler 线程控制

    第七章、 IOC 架构设计

  • 第一节、 依赖注入与控制反转

  • 第二节、ButterKnife 原理上篇、中篇、下篇

  • 第三节、Dagger 架构设计核心解密

    第八章、 Android 架构组件 Jetpack

  • 第一节、 LiveData 原理

  • 第二节、 Navigation 如何解决 tabLayout 问题

  • 第三节、 ViewModel 如何感知 View 生命周期及内核原理

  • 第四节、 Room 架构方式方法

  • 第五节、 dataBinding 为什么能够支持 MVVM

  • 第六节、 WorkManager 内核揭秘

  • 第七节、 Lifecycles 生命周期


    本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

img-ROxDKCkx-1713585824726)]
本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
[外链图片转存中…(img-l0UbTfNB-1713585824727)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值