前言
持续了大半年的面试终于结束了,自从 5 月被前公司优化之后,一直陆陆续续有面试邀约。
收获 offer 还是比较满意的,拿下了小红书、小米的 offer。着实有点可惜的是汽车之家,倒在了三面,只能说自己还是太菜,以后还需要继续努力。
这期间只投递了互联网中大厂,面试并不多,以下是我在这大半年以来的面试经历,发出来总结一波,也供大家参考参考!
以下面试均为 Android 开发的社招岗。
汽车之家
- 看简历上掌握 Kotlin,说一说协程:考察 Kotlin 协程的基本原理、挂起函数与恢复函数的区别,以及协程在异步任务中的优势。
- 说一说 Java 的反射?反射为什么性能差?:涉及反射机制的实现原理,动态获取类信息,以及因安全检查导致的性能损耗。
- 熟悉 Android 的四大组件,说一说 Activity 的 launchMode 中的 singleTask 和 singleTop 的区别:重点在于任务栈的管理策略及实例复用逻辑。
- provider 中 getContext() 获取到的 context 是什么 context?:考察 Context 类型的区分(Application, Activity, Service)及其生命周期影响。
- 协程是什么?:基础概念,轻量级线程,结构化并发。
- 知道集合和多线程,那说一说你知道的线程安全的集合:如 ConcurrentHashMap, CopyOnWriteArrayList 等及其内部实现。
- 讲一讲你知道的锁?从不同角度可以分为类锁和对象锁、公平锁和非公平锁、乐观锁和悲观锁,追问自旋锁:深入 JVM 层面的锁升级过程(偏向锁->轻量级锁->重量级锁)。
- 讲一讲 LeakCanary 的原理(弱引用队列+Activity 生命周期),使用 LeakCanary 检测到了什么内存泄漏?是先知道这里会出现内存泄漏吗?:分析 WeakReference 队列机制及 GC Root 的判定逻辑。
- LeakCanary 用到了一个 GC 机制,GC Root 都有哪些?:静态变量、活动对象、栈帧局部变量等。
- 阅读文章的 App,这些文章有做本地存储吗?具体实现?:考察 SQLite, Room, SharedPreferences 或文件 IO 的使用场景。
技术解析
在汽车之家面试中,除了常规组件知识,对底层原理的考察非常细致。特别是关于内存管理和并发编程的部分,面试官倾向于询问具体的实现细节而非泛泛而谈。例如在锁机制方面,不仅要求说出分类,还要求解释自旋锁在 CPU 调度中的行为。LeakCanary 作为常用的内存检测工具,其背后的弱引用队列和 GC Root 追踪机制是理解 Android 内存模型的关键。
小红书
- Handler 机制是什么?在没有 message 的时候为什么不会导致应用程序 ANR?:Handler 消息循环机制,Looper 的阻塞等待原理。
- 介绍一下四大组件?:Activity, Service, BroadcastReceiver, ContentProvider 的基本职责。
- Activity 启动模式?:Standard, SingleTop, SingleTask, SingleInstance 的区别与应用场景。
- 进程和线程的区别?:资源分配单位 vs 执行单元,上下文切换成本。
- 你知道 Android 程序的入口吗?知道 ActivityThread 吗?:main 方法调用 Application.attach 的过程。
- View 的事件分发机制?View 的绘制机制?:onInterceptTouchEvent, dispatchTouchEvent, onDraw 流程。
- 如果要在一个 Activity 里面获取一个 View 的宽高应该在哪一个回调方法获取?:post, onSizeChanged, layout 回调等时机选择。
- 知道共享内存模型吗?:Android IPC 机制的基础。
- 内存里面的寄存器有了解吗?指针寄存器?指令寄存器?:计算机组成基础,CPU 架构相关。
- LeakCanary 原理?弱引用和软引用区别?:SoftReference 允许在内存不足时被回收,WeakReference 则不受限。
- 讲一讲泛型?泛型的原理?类型擦除,擦除之后呢?如何获取类型?:TypeToken 的使用,反射获取泛型信息。
- 协变和逆变?in 和 out 如何选择:Kotlin 中的声明处方差控制。
- 高阶函数?:Lambda 表达式,函数作为参数传递。
- Git 的原理?:分布式版本控制,快照机制。
- 面向对象编程和响应式编程的区别?:命令式 vs 声明式,数据流管理。
- Map?Map 的时间复杂度,什么时候会用到链表化和树化,哈希冲突,有了解 HashMap 的扩容吗?如果是你会怎么做?:JDK 1.8 后的红黑树转换阈值,负载因子。
- 为什么要使用 TCP 协议?TCP 协议有什么好处?TCP 协议解决了什么问题:可靠性传输,流量控制,拥塞控制。
- 说一下你最熟悉理解最深的一个知识点?说了 JVM 的内存划分机制:堆,栈,方法区,垃圾回收算法。
技术解析
小红山的面试风格偏向于广度与深度的结合,既考察基础理论(如寄存器、网络协议),也关注实际工程问题(如 View 测量、HashMap 扩容)。对于 Handler 机制的提问,重点在于理解 Looper 的消息队列循环如何避免 ANR。此外,对 JVM 内存模型的考察表明了对底层性能的重视。
小米
- 泛型擦除的概念。什么时候用:编译期检查,运行期类型安全。
- ThreadLocal 原理,内存泄漏的原因:ThreadLocalMap 的 Key 为弱引用,Value 为强引用,需手动 remove。
- 知道哪些数据压缩算法:Gzip, Deflate, LZ4 等。
- dns 挟持是什么,哪些解决办法:DNS 劫持,修改 hosts,使用 DoH/DoT。
- Charles 怎么抓 https 的包:安装证书,配置代理。
- java 四种引用类型:强,软,弱,虚引用。
- jvm 有哪几种 gc 算法,分代收集新生代老年代分别使用哪一种:标记清除,复制,标记整理;新生代复制,老年代标记整理。
- 数据库第三范式:消除冗余,保证一致性。
- http 状态码:200, 301, 404, 500 等含义。
- https 的流程:SSL/TLS 握手,密钥交换。
- tcp 四次挥手:FIN, ACK 交互过程。
- dns 解析过程:缓存,递归查询,迭代查询。
- 为什么 hashmap 链表是尾插:避免链表反转,提高插入效率。
- concurrenthashmap 为什么不可以存 null 的 key 而 hashmap 可以:定位桶位置时的判断逻辑。
- equals 和 hashcode:重写规范,哈希表查找前提。
- 线程池怎么配置参数保证有序:LinkedBlockingQueue, FixedThreadPool。
- synchronized 底层原理:monitorenter, monitorexit, 锁膨胀。
- cas 的缺点,怎么解决:ABA 问题,版本号机制。
- http2.0 和 http3.0:多路复用,二进制分帧,QUIC 协议。
- 快重传和快恢复:TCP 拥塞控制算法。
- cookies 和 session:客户端存储 vs 服务端存储。
- 五层网络结构,每一层有哪些协议:物理层,数据链路层,网络层,传输层,应用层。
技术解析
小米的面试题覆盖面极广,从底层 JVM 到上层网络协议均有涉及。特别是计算机网络部分,TCP/IP 模型、HTTP 协议细节是必考项。同时,对并发编程的考察非常深入,包括 CAS 原子操作、线程池参数调优以及 ThreadLocal 的内存泄漏防护,这些都是生产环境中常见问题的核心。
得物
- activity 的生命周期,各个阶段的方法名叫什么:onCreate, onStart, onResume, onPause, onStop, onDestroy。
- 安卓的那些场景会导致内存泄漏:单例持有 Context,非静态内部类,未注销的广播/监听器。
- c++ 的垃圾回收机制:C++ 无自动 GC,需手动管理或使用智能指针。
- tcp 的三次握手和四次挥手:连接建立与释放的标准流程。
- 为什么 tcp 客户端的 time-wait 状态必须等待 2MSL:确保最后一个 ACK 到达,防止旧连接干扰。
- http1.1 与 http2.0 之间的区别:多路复用,头部压缩,二进制传输。
- 线程安全的解决思路:同步,不可变对象,线程局部存储。
- 有哪几种锁:互斥锁,读写锁,自旋锁,信号量。
- 进程通信方式,具体的使用场景:管道,消息队列,共享内存,Socket。
- 二叉树的深度遍历,递归与非递归实现:DFS 算法实现。
- c++ 的内存模型,各个区的作用:代码段,数据段,堆,栈。
- c++ 什么情况下会有野指针问题:未初始化,已释放仍使用。
- 还有什么情况下会有野指针问题:数组越界访问,悬空指针。
- 链表,有一个指针,双指针,在引用的过程中间,有一个指针将他的链给断开,去访问的时候,另一个指针会发生什么:指针失效,内存访问错误。
- 数组的越界呢?:未定义行为,可能崩溃或读取脏数据。
- 文件的内存映射了解过吗?相较于普通的 io 流有什么优势呢:mmap,减少系统调用,零拷贝。
- 一个数组的值先从小到大递增后从大到小递减,找出最大的值:二分查找变种,寻找峰值。
技术解析
得物的面试侧重于 C++ 与 Android 的结合,以及对底层数据结构与算法的考察。除了常规的 Android 生命周期,还涉及了操作系统层面的内存管理、指针安全以及网络协议细节。算法题部分虽然题目描述简短,但往往考察的是对边界条件的处理和对经典算法的灵活运用。
OPPO
- 讲一讲项目?数据获取流程?:业务逻辑梳理,网络请求封装。
- 讲一讲四大组件:基础组件功能回顾。
- 讲一讲集合类:List, Set, Map 的实现差异。
- 讲一讲 Handler 机制:消息队列处理。
- 事件分发机制,事件拦截在哪个方法中拦截?了解触摸事件吗?:onInterceptTouchEvent 返回值决定。
- View 绘制机制,追问 ViewGroup 的绘制过程?然后问到了根 View,Window?:measure, layout, draw 三步骤。
- View 是一个树形结构,如何遍历?深搜,广搜,讲一讲深搜,广搜:递归遍历 vs 队列遍历。
- 垃圾回收机制?具体问了分代回收算法,GC ROOT 有哪些?你觉得 GC root 引用链是一个什么结构,不清楚?:对象图遍历,可达性分析。
- 进程、线程、协程的区别:资源粒度与调度单位。
- 有做数据库本地保存操作吗?如何实现的?有使用过什么框架没?:Room, Realm 等 ORM 框架。
- 最后一个问题,讲一讲架构模式,MVC、MVP、MVVM 模式:解耦设计,数据绑定。
技术解析
OPPO 的面试流程较为全面,从项目经验到技术细节层层递进。特别关注架构设计的合理性,如 MVVM 模式在实际项目中的应用。View 系统的遍历与绘制机制也是高频考点,要求候选人不仅会用,还要懂原理。此外,对 GC Root 引用链结构的追问,显示了对内存管理底层逻辑的重视。
小天才
- ARouter 的原理?:注解处理器,反射路由跳转。
- MVP,MVVM 模式相对于 MVC 模式的优势?:解耦,测试友好,数据驱动。
- 知道六大设计原则吗?不太清楚具体都有什么。说一下除了单例模式之外的两个设计模式:SOLID 原则,工厂,观察者等。
- 事件分发的过程?onClick 和 onTouchEvent,onTouch 哪个先执行?(onTouch>onTouchEvent>onClick):事件分发顺序。
- 如果现在出现了横向滑动和竖向滑动的冲突,你会如何解决?如果获取到的 x 移动距离和 y 移动距离一样大如何定义逻辑?:requestDisallowInterceptTouchEvent 配合手势判断。
- 使用 Glide 有做一个封装吗?应该封装到一个工具类里面来做复用:图片加载库的二次封装。
- 讲一讲内存泄漏和内存溢出?为什么会内存泄漏?列举三种内存泄漏的情况:静态集合,单例,匿名内部类。
- 有做过性能优化吗?说了包体积优化,布局优化。内存泄漏优化其实也是:ProGuard, 懒加载,异步加载。
- 说一下具体写过的自定义 View?:Canvas 绘图,触摸事件处理。
- Activity A 跳转到 Activity B 再按下 back 键回到 Activity A 各自的生命周期变化?如果按下 back 键回到 Activity A 之后发现 Activity B 没有调用 onDestory() 方法你会如何去调试找 bug?:日志打印,Dumpsys 分析。
- 100 个任务放入到线程池,如何设计最快的完成任务。如何要在前面 99 个任务执行完成之后再执行第 100 个任务呢,如何设计?:CountDownLatch, Future 机制。
- 项目中遇到的难点?异步场景下的数据同步。如何解决?接口回调的场景下,如果数据还没有返回,但是用户终止了应用程序,你觉得你的设计有什么问题和解决方法?内存泄漏如何解决?弱引用:生命周期感知,弱引用清理。
- 面试官介绍小天才部门的基本情况和业务:业务背景了解。
技术解析
小天才的面试非常注重实际工程能力的落地,包括自定义 View、性能优化、复杂场景下的并发处理。对于 Activity 生命周期的异常排查(如 onDestory 未调用)提出了具体的调试思路。此外,对设计模式和架构模式的考察,旨在评估候选人的代码抽象能力和长期维护意识。
核心知识模块概览
为了系统化复习上述面试内容,我们将知识点划分为以下七大模块,每个模块均包含高频考点与核心原理。
第一章 Java 方面
- Java 基础部分:基本数据类型,String 不可变性,Object 常用方法。
- Java 集合:ArrayList 扩容,LinkedList 节点结构,HashMap 源码分析。
- Java 多线程:线程创建,ThreadLocal,volatile 关键字,synchronized 锁升级。
- Java 虚拟机:内存区域划分,垃圾回收算法,类加载机制,JVM 调优参数。
第二章 Android 方面
- Android 四大组件相关:启动模式,Service 生命周期,Broadcast 注册方式。
- Android 异步任务和消息机制:Handler, MessageQueue, Looper, AsyncTask (废弃)。
- Android UI 绘制相关:ViewRootImpl, MeasureSpec, Canvas 绘制流程。
- Android 性能调优相关:ANR 排查,OOM 分析,卡顿监控,启动速度优化。
- Android 中的 IPC:Binder 机制,AIDL 使用,Messenger 通信。
- Android 系统 SDK 相关:Context 类型,Intent 隐式显式,ContentProvider 权限。
- 第三方框架分析:Retrofit, OkHttp, Glide, RxJava 原理。
- 综合技术:Gradle 构建,ProGuard 混淆,多渠道打包。
- 数据结构方面:链表,树,图,哈希表,排序算法。
- 设计模式:单例,工厂,观察者,策略,适配器模式。
- 计算机网络方面:HTTP/HTTPS, TCP/IP, DNS 解析,Socket 编程。
- Kotlin 方面:协程,扩展函数,委托属性,空安全。
第三章 音视频开发高频面试题
- 编码原理:为什么巨大的原始视频可以编码成很小的视频呢?这其中的技术是什么呢?(压缩算法,离散余弦变换)。
- 直播优化:怎么做到直播秒开优化?(预加载,CDN 加速,首屏渲染优化)。
- 图像处理:直方图在图像处理里面最重要的作用是什么?(亮度分布分析)。
- 滤波方法:数字图像滤波有哪些方法?(高斯滤波,中值滤波)。
- 特征提取:图像可以提取的特征有哪些?(边缘,角点,纹理)。
- 重建标准:衡量图像重建好坏的标准有哪些?怎样计算?(PSNR, SSIM)。
第四章 Flutter 高频面试题
- Dart 部分:异步编程,Future, Stream, Isolate。
- Flutter 部分:Widget 树,RenderObject 树,StatelessWidget vs StatefulWidget。
第五章 算法高频面试题
- 素数寻找:如何高效寻找素数(埃拉托斯特尼筛法)。
- 二分查找:如何运用二分查找算法(边界条件处理)。
- 雨水问题:如何高效解决雨水问题(双指针,单调栈)。
- 数组去重:如何去除有序数组的重复元素(原地修改)。
- 模幂运算:如何高效进行模幂运算(快速幂算法)。
- 最长回文子串:如何寻找最长回文子串(中心扩散,Manacher 算法)。
第六章 Android Framework 方面
- 系统启动流程面试题解析:Bootloader, Kernel, Init, Zygote, SystemServer。
- Binder 面试题解析:Binder 驱动,Binder 服务,跨进程通信。
- Handler 面试题解析:Message 对象池,Looper 死循环。
- AMS 面试题解析:ActivityManagerService, 进程管理,任务栈。
第七章 企业常见 174 道面试题
- SD 卡:外部存储权限,路径获取。
- Android 的数据存储方式:SharedPreferences, SQLite, File, Network。
- Broadcast Receiver:静态注册,动态注册,有序广播。
- sp 频繁操作会有什么后果?sp 能存多少数据?:主线程阻塞,容量限制。
- dvm 与 jvm 的区别:Dalvik 虚拟机 vs Java 虚拟机,字节码格式不同。
- ART:Android Runtime,AOT 编译,内存占用优化。
- Activity 的生命周期:状态流转图。
- Application 能不能启动 Activity:需要 FLAG_ACTIVITY_NEW_TASK。
结语
面试不仅是技术的较量,更是心态与准备的博弈。通过整理这些大厂的面经,希望能帮助正在求职的开发者们查漏补缺,构建更完整的知识体系。建议大家在复习时,不仅要记住答案,更要理解背后的原理,能够举一反三。祝各位都能拿到心仪的 Offer!