尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Android校招笔试题解析:从Handler到Binder,掌握核心机制与性能优化

Android校招笔试题解析:从Handler到Binder,掌握核心机制与性能优化 老实说每年校招放出笔试题的时候刷题群里最热闹的就是讨论“这题到底想考什么”。小红书这套2020校招Android方向笔试题卷三我在准备面试的时候也对着做过一遍现在回头看很多考点其实不只是考“会不会”而是考“有没有真正做过东西”。尤其Android方向的卷子堆知识点的人能过初筛但想拿高分还是得看你能不能讲清楚机制、说透原理。这篇内容不贴原题只把卷子背后真正想考察的知识体系和答题思路拆开讲清楚准备校招的同学可以直接对标复习已经工作的人也可以拿来自查基础。1. 这套笔试题在筛选什么——先看懂出题人的意图1.1 校招笔试题的底层逻辑很多同学拿到卷子就开始闷头做题其实第一件事应该是判断难度梯度和出题侧重点。小红书这种内容型App的Android团队日常要面对的是复杂列表、图片加载、消息推送、跨进程通信、性能优化这些高并发高交互场景所以笔试题不会只考语法背诵而是围绕“能不能独立扛起一个模块”来设计。卷三这类套题通常分三层基础语言与内存、Android核心机制、算法与设计能力。从通过率来看大部分人挂在中间那一层也就是Handler、Binder、View事件分发这些机制题上因为这些光靠背八股文是答不透的。1.2 从热词反推考点范围如果你去看评论区或者面经会发现大家讨论度最高的是AMS、Activity启动流程、R8混淆、组件通信、性能优化这几个词。结合小红书的业务场景图片加载、列表复用、弱网处理、消息触达都是重点。所以在准备这套题的时候不能只抱着Java基础书啃得把Android的四大组件、消息循环、进程通信、View体系、图片加载、网络请求这几条主线全部串起来复习。我建议用脑图把每个考点展开成“是什么—为什么—怎么用—常见坑”四个层级这样遇到问答题才有的写。2. Java与Kotlin基础以及内存与并发——笔试题的第一道分水岭2.1 内存模型与GC回收机制卷三的开头部分一般会围绕JVM内存区域、可达性分析、GC算法和内存泄漏来出题。这题看着基础但想答出区分度不能只写“堆内存、栈内存、方法区”这种教科书定义。我自己的答题思路是先讲清楚对象的分配路径比如通过new创建的对象在Eden区分配大对象直接进老年代Minor GC和Full GC的触发条件是什么然后结合Android场景说明为什么内存泄漏在Android上危害更大——因为移动端内存有限一个泄漏的Activity可能就意味着整个页面无法回收最终OOM。答到这里面试官基本能确认你不是死记硬背。之所以很多人在这一步翻车是因为他们不了解可达性分析算法里GC Roots到底是什么。这块我建议从两个角度去理解一是栈帧里的局部变量、静态变量、JNI引用都属于GC Roots二是Java里的循环引用其实不会被判死因为GC Roots根本到不了它们。像LeakCanary检测内存泄漏的原理本质上就是等Activity onDestroy之后触发一次GC再判断这个Activity实例有没有被GC Roots链引用如果有人为持有的强引用链在就说明泄漏了。把这个机制理解透不管是选择题还是简答题都能应对。2.2 线程、锁与并发——最容易暴露真实水平的地方并发题在校招卷子里占比不低而且特别能拉开差距。常见考法有synchronized和ReentrantLock的区别、volatile的可见性与指令重排、线程池的核心参数、死锁的产生条件和避免方式。这些知识点如果你想拿高分光说出概念是不够的我建议每个点都准备一个场景化例子。比如线程池核心参数可以直接用“一个图片下载线程池”来现场推导核心线程数应该设置多少队列用什么类型拒绝策略用哪个为什么要这样选。只有当你能把参数跟业务场景绑定起来面试官才会觉得你不是“背答案”。其实还有一个容易被忽略但很常考的点就是ThreadLocal。很多人只知道ThreadLocal是线程变量隔离的但不知道它的底层实现是一个ThreadLocalMap以当前ThreadLocal作为keyvalue存在每个线程自己的Thread对象里。更重要的是Handler机制里的Looper就是靠ThreadLocal实现的——每个线程looper只能有一个但一个线程可以有多个Handler。把这些关联起来答一道基础题就能体现出源码阅读能力。2.3 集合框架与泛型的几个高频坑集合这块卷子里喜欢考HashMap的底层原理、扩容机制、put过程、红黑树引入条件再拿ArrayList和LinkedList做对比。HashMap的考点比较固定但还是有人答错一个点在JDK 1.8里链表转红黑树的条件是数组长度大于等于64且链表长度大于等于8不要把阈值记漏了。另一个常考的是HashMap为什么线程不安全这就要联系到resize时可能出现的环形链表问题以及JDK 1.8后虽然改进了头插法但多线程put依然可能丢数据。这些细节在选择题里尤其容易当陷阱出现。泛型题比较少但如果出到通配符、类型擦除很多人会懵。我给的复习建议是记住一句话Java泛型在编译后都会被擦除为原始类型运行时你是拿不到泛型T的类型Class的。所以后面你看到Gson解析泛型需要用TypeToken本质就是因为类型擦除之后无法直接获取泛型参数Reflect API里生僻的Type接口这时候才派上用场。这套题后面如果结合三方框架来问多半就落在这种考点上。3. Handler、Looper与Binder——Android机制题的核心阵地3.1 Handler消息机制的整体链路小红书这类App对主线程流畅度要求极高所以Handler是笔试题里的绝对核心。常见问题包括一个线程有几个Looper几个HandlerHandler的sendMessage和postDelay的区别主线程Looper为什么不会因loop死循环而卡死。前两个问题还好第三个问题几乎人人都卡壳。我的理解是主线程确实在执行死循环但是当消息队列为空时底层epoll机制会让线程睡眠等待此时不占用CPU有消息时通过管道唤醒。Android之所以不用普通wait/notify是为了能处理Native层的消息事件比如Choreographer的VSYNC回调就是走这个通道的。答题时我还会补一个内存泄漏的考点非静态内部类Handler会隐式持有外部Activity的引用如果我们在Activity销毁后消息队列里还排着延迟消息这条消息就会持有HandlerHandler又持有Activity导致Activity无法被回收。解决方式大家都背过用静态内部类加WeakReference。但更进一步的问法是为什么用静态内部类加弱引用还不够因为如果还有其他长生命周期对象持有这个Activity泄漏照样存在。这样一层层递进才是高分答案的模式。3.2 ThreadLocal在Looper中的关键作用Looper的实现里有一个特别值得单独拿出来的细节点ThreadLocal的set和get。每个线程对象内部都有一个ThreadLocalMapThreadLocal只是充当一个key。每次我们通过Looper.myLooper()拿到当前线程的Looper时本质上是往Thread.currentThread()这个线程的ThreadLocalMap里取值。这个机制就保证了“一个线程只有一个Looper但一个Looper可以被多个Handler共用”。笔试如果给了源码片段最喜欢在初始化这段出题static final ThreadLocalLooper sThreadLocal new ThreadLocalLooper();问你为什么用static修饰、为什么用ThreadLocal。这两问其实考的是同一个东西静态修饰保证全局只有一份ThreadLocal实例ThreadLocal保证每个线程拥有自己的Looper副本。把这层逻辑讲透比单纯背“ThreadLocal是线程局部变量”有用得多。3.3 Binder与跨进程通信跨进程通信是小红书笔试题里的进阶大户主要考Binder相比其他IPC方式的优势、AIDL的工作流程、以及一次拷贝的原理。Binder的优点大家都会背性能高、安全、只需要一次拷贝。但有一次面试官追问我为什么Binder只要一次拷贝而传统方式要两次这个追问需要有Linux内核和虚拟内存的支撑。常规理解是Binder在内核空间分配了一段缓冲区通过copy_from_user把数据从用户空间拷贝到内核空间然后在目标进程通过内存映射把这段内核缓冲区映射到用户空间所以不需要再往目标进程用户态拷贝第二遍。虽然Android 14之后引入了一些新机制但校招笔试的答案层面这一条逻辑链足够清晰。AIDL这块如果有代码题很可能是让你把AIDL接口补齐或者让你说清楚Stub和Proxy分别干了什么。我的记忆方法是Stub是服务端的binder实体Proxy是客户端的代理对象。客户端调用Proxy的方法Proxy负责把参数序列化后通过transact发给服务端服务端Stub的onTransact反序列化参数并调用真正的业务方法。把这条链路画出来笔试题基本不会丢分。4. View体系与事件分发——实战能力最直观的体现4.1 测量、布局和绘制的顺序与要点小红书首页的瀑布流、评论列表、图片混排每一块都依赖View体系的深入理解所以笔试题几乎必考自定义View流程。典型问题包括MeasureSpec的三种模式、onMeasure里为何要调用setMeasuredDimension、ScrollView嵌套RecyclerView怎么解决测量问题。这些题的共同底层逻辑是View的尺寸由父View的MeasureSpec和自己的LayoutParams共同决定父View传下来的是约束子View在这个约束范围内决定自己的尺寸。关于自定义View我一定会在答题中强调resolveSize和MeasureSpec的配合。很多人直接写死一个大小没去管padding导致后面嵌入各种场景时出现显示异常。比如你在onDraw里用getWidth()画了一条线但当父容器是wrap_content时getWidth()取决于你自己在onMeasure里设置的measureDimension。如果尺寸处理不对这条线要么超出父容器要么缩成一团。这些都是笔试题中容易出“判断题”的点没有亲手写过自定义View的人很难避开。4.2 事件分发机制的核心源码逻辑事件分发绝对是卷三的压轴常客。考点一般是down事件怎么从Activity传到ViewdispatchTouchEvent、onInterceptTouchEvent、onTouchEvent的调用顺序requestDisallowInterceptTouchEvent的作用。这里我建议背熟一个简单的规律事件分发是从外到内的“询问”过程事件处理是从内到外的“回溯”过程。Down事件如果某个View没有消费那后续move和up事件也轮不到这个View处理。如果出代码填空题很可能让你判断点击结果配合Log输出判断哪个方法被调用。这种题最容易错的是忽略onTouchEvent的返回值对事件流的影响。一个View如果只处理了ACTION_DOWN但返回false整个事件序列就断了如果只处理了ACTION_MOVE返回truedown事件时没返回true后面也不会有move。这就是为什么自定义View处理事件时要格外小心不能只看单个事件要看整个事件序列。4.3 滑动冲突与常见场景滑动冲突的题目一般以综合题出现问你如何解决垂直ScrollView嵌套水平RecyclerView的滑动冲突。解题思路不外乎两种外部拦截法和内部拦截法。外部拦截法的核心是在父View的onInterceptTouchEvent中判断当父容器正在垂直滑动且事件为move时就拦截如果判断为子View的横向滑动就放行。内部拦截法则是子View通过requestDisallowInterceptTouchEvent阻止父容器拦截同时父View的onInterceptTouchEvent还需要做特殊处理——除了down事件其他事件都返回false。笔试里写伪代码时我比较推荐外部拦截法因为逻辑简单、不容易出Bug。但要注意外部拦截不是所有场景都好用。比如需要在Header和Content区域进行不同滚动的复杂页面外部拦截法会让联动非常难做这时候就需要改用内部拦截法或者用事件流重组的方式。能答到这里说明你确实处理过复杂页面嵌套的场景比只背结论要强很多。5. 四大组件、AMS与进程管理——Android系统的骨架5.1 Activity启动模式与Intent FlagActivity的四种启动模式是校招笔试题的“必背题”几乎不会缺席。standard、singleTop、singleTask、singleInstance之间的区别尤其是singleTask的栈亲和性以及什么是taskAffinity考得特别细。除了这四种模式还有一种常见考法就是结合Intent Flag来问你两个flag同时设置时会发生什么比如FLAG_ACTIVITY_NEW_TASK和FLAG_ACTIVITY_SINGLE_TOP。或者问你怎么从外部应用拉起一个Activity而不希望它进入当前Activity所在栈这就得答singleInstance。我的理解方式是把启动模式当成“任务栈管理策略”而不是单纯的Activity行为。singleTop只处理栈顶复用singleTask处理整个栈内的复用并清掉目标Activity之上的所有界面singleInstance则是开了一个独立的新栈专门给全局唯一的Activity使用。小红书这种工具型App里比如从推送点开一个详情页如果详情页已经在栈里应该用singleTask把之前的详情页实例调到前台而不是新建一个。这其实就是singleTask在日常编码里的一个典型应用。5.2 Activity启动流程——从startActivity到onCreateActivity启动流程是卷子里少数能把“基础”和“进阶”拉满的大题。简单版本是startActivity最终会走到AMS的startActivityAMS校验调用者权限、处理task、检查进程是否存在如果进程不存在就通过Zygote fork出新的进程然后在新进程里通过ActivityThread的handleLaunchActivity走到onCreate。高分答案需要补充更多细节比如Application和Activity的创建顺序、Instrumentation在中间扮演的角色、以及为什么新进程启动Activity时Application先初始化。这里想特别提醒一句不要只背自己开发的App那一层要想清楚AMS运行在系统进程内是通过Binder调用ActivityThread的scheduleLaunchActivity的ActivityThread这个对象才是App进程里真正的主线程入口。很多同学忽略这一点容易把ActivityThread和Activity弄混。答启动流程这类综合题时把“系统进程—App进程—ActivityThread—Activity”这条线串明白基本就能甩开一大批人了。5.3 进程优先级、保活与优化进程管理这块小红书这类对体验要求高的团队一定会考察App被系统回收的优先级机制。Android进程从高到低依次是前台进程、可见进程、服务进程、缓存进程。面试官可能通过一个场景题来考App切换到后台后Activity还可见吗如果不可见但还有一个前台服务在播放音乐进程属于哪一级这种题如果概念不牢很容易答错。正确的判断标准是进程优先级取决于进程内当前最高优先级组件而不是所有组件的平均值。关于保活的话题现在校招其实越来越少出那种“如何不被杀死”的偏门题反而更关注“如何优雅地处理进程被系统回收后的状态恢复”。因此我建议复习时多关注onSaveInstanceState、ViewModel在配置变更时的存活机制以及多进程架构下的通信与数据同步。对于一篇2020年左右的笔试题可能还会出现“怎么判断App是否处于后台”这种题这就有很多种方案了从前台Service标志位、ActivityLifecycleCallbacks统计、到Application的ProcessLifecycleOwner最好每种方案都能说出优缺点。6. 网络、图片与性能优化——贴近业务场景的综合应用6.1 网络框架与HTTP/HTTPS考点从热词看几乎每套Android笔试都会涉及网络层。常见考法是HTTP和HTTPS的区别、TCP三次握手与四次挥手、如何设计一个网络请求框架、OkHttp的拦截器机制、以及Retrofit动态代理原理。这些都是实用性比较强的题目因为客户端开发绕不开网络。答HTTP和HTTPS的时候不要只写“HTTPS多了一层SSL/TLS”最好补充证书验证的详细流程包括客户端如何校验服务端证书、中间人攻击怎么防范、以及为什么需要CA。Retrofit的动态代理也是卷子里容易出的一道进阶题。它的工作原理是用Java动态代理为接口生成一个代理对象在InvocationHandler的invoke方法里解析方法上的注解和参数拼装成ServiceMethod再通过OkHttp发起网络请求最后用Converter将响应体转成目标对象。如果你能从动态代理、注解解析、CallAdapter这几个层面回答面试官基本能确认你是真正读过框架源码而不只是会调用API。6.2 图片加载与内存缓存策略小红书是典型的图片密集型App图片加载这一题出现的概率非常高。考点主要围绕Glide和Fresco的缓存策略、三级缓存、Bitmap的内存优化、以及图片采样率的计算。关于Glide大家都会说内存缓存加磁盘缓存加网络加载但如果问具体内存缓存的Key是如何生成的或者为什么Glide默认使用RGB_565而不是ARGB_8888能答上来的人就少了很多。有个高频计算题是给一张分辨率为1080x1920的图片加载到内存时需要多大内存。计算公式是宽乘高乘每个像素所占用的字节数。ARGB_8888每个像素占4字节RGB_565占2字节所以前者的计算结果是1080乘1920乘4约8.3MB。如果面试官再追加一句“图片被放在ImageView中显示会不会压缩内存”就要答Bitmap在解码时就会根据采样率生成缩小后的内存占用而ImageView的scaleType只是显示层面的缩放不会改变Bitmap本身的内存大小。这个陷阱很多没做过图片优化的人都会踩。6.3 性能优化与启动速度性能优化类的综合题一般放在最后比如“如果让你优化小红书的冷启动速度你会怎么做”。这种题没有标准答案但有一个清晰的答题框架先量化指标再分层优化。冷启动阶段可以分为Application初始化、首帧绘制、页面数据加载三块。Application里如果有大量第三方SDK的初始化可以考虑延迟初始化到子线程或者用Service懒加载首帧绘制要减少主线程耗时比如不使用多余的布局层级、使用ConstraintLayout、减少不必要的measure和layout数据加载方面则可以使用本地缓存、异步加载、预加载等策略。另一个常驻考点的性能优化是崩溃率。“你如何排查一个偶现的Native崩溃”这种题答案可以围绕Logcat、tombstone、bugly等工具展开。如果你能说出利用addr2line解析so的堆栈那就更能体现你的底层能力。这套题考到性能优化的本质就是想看候选人有没有线上思维而不仅仅是会写界面。7. 算法与数据结构——笔试题里的基础分7.1 高频算法题型分析小红书的算法题不会特别偏门主要集中在数组与链表操作、二叉树遍历、字符串处理、动态规划和二分查找。这一部分拼的是平时的基本功。对于这种难度的卷子我建议准备一个“高频算法清单”链表的反转、合并有序链表、判断链表是否有环二叉树的层序遍历、最近公共祖先数组的双指针、快排和归并字符串的滑动窗口经典的爬楼梯、最长上升子序列等简单到中等难度的动态规划。算法题在校招笔试里往往直接与是否进入面试挂钩是刷人最狠的部分。如果时间有限我不赞成盲目刷几百道题而是建议按题型分类刷。你得保证看到一道题能先判断出题型和复杂度级别再动笔写。比如看到“寻找两个有序数组的中位数”首先想到时间复杂度至少要对数级别那就别写排序了要朝二分法思路想看到“两数之和”立刻想HashMap优化看到“最长无重复子串”就是滑动窗口加哈希表。有了这个思路同样的题就算没刷过也能推进下去。7.2 手写代码的答题策略笔试里手写代码最忌讳一上来就写。我个人的习惯是先在注释里标记边界条件和测试用例再在纸上或者编辑器里逐步填充。比如写链表反转时先问自己如果链表是空的怎么办如果只有一个节点怎么办循环终止条件是什么这些边界条件在笔试的判分系统里往往是扣分重灾区。另外现在很多在线笔试平台会让你选择语言。如果你Java基础一般而其他语言更熟尽量不要因为“岗位是Android所以必须写Java”而逼自己用Java。笔试更重要的是考察思路和正确性用Kotlin写也完全没有问题。不过如果你决定用Java那就必须把HashMap、ArrayList、PriorityQueue这些常用容器的API记准确不要在简单语法上浪费不必要的时间。8. 备考路径与实战心得——给准备校招的你一些具体建议8.1 三轮复习法的时间安排针对小红书2020校招Android方向笔试题卷三这类套卷我的备考建议是三轮复习法。第一轮花两周左右把所有基础考点过一遍重点看Java基础、集合、并发、虚拟机每天的节奏是至少一个小时的算法题加两小时的基础知识点睡前用Anki这类工具复习错题。第二轮进入Android专项把Handler、Binder、View体系、四大组件、图片加载、网络框架等内容按专题刷完每一个理论知识点都要配一个Demo验证比如自己写一个自定义View来验证事件分发写一个跨进程AIDL来体验Binder的流程。第三轮就是真刀真枪地做整套卷子限时训练重点练做题速度和考点联想能力。这个方法听起来没什么特别但它是“输入—消化—输出”的闭环。很多同学刷题只停留在“输入”以为自己看懂了结果在笔试现场写不出来。所以我在第二轮花的时间最多所有知识点都动手实验一遍。比如Handler机制我专门写了一个子线程自己创建Looper的Demo对比主线程Handler的日志输出Binder那一块我分别写了系统自带AIDL和手动实现Binder两种方式确保自己真正理解Stub和Proxy的调用关系。8.2 答题时的表达与时间分配笔试如果全是客观题时间分配还相对宽松但如果是主观题加编程题就得有点策略了。我自己的分配原则是这样的先把所有题目扫一遍区分出“会做”和“可能不会做”优先拿稳会做的分数不会做的题目也一定要写点思路不要空着。Android机制类主观题即使不确定源码细节也要把大致流程写出来并且标注一下“如果有HashMap的扩容源码细节应该在某个版本之后有调整”这样好的采分点依然能覆盖到。因为这是2020年左右的题目有些知识点可能已经有所迭代比如启动模式在Android 10之后的限制和Binder在Android 14之后的调整但基础原理没有变。如果你复习的是最新版本建议考试时顺带从“通用原理”和“版本演进”两个维度来回答既能体现深度又能体现对新技术趋势的关注。8.3 面试官真正想看的三个素质最后结合我带实习生的经验总结一下这类笔试题真正想看到的素质。第一是主动性和好奇心比如同样的Handler机制你被问到底层为什么不会被卡死如果自己都没有去查过epoll这道题再背八股文也白搭。第二是抽象建模能力面对一个自定义View的测量题你的脑海里能迅速把它抽象成一棵树知道每个父容器在往上“压”约束子View在往下“反馈”数值这种建模能力决定了你能不能在复杂业务里快速定位问题。第三是代码规范性就算笔试不要求运行通过你的变量命名、空指针判断、注释逻辑面试官都会一一看在眼里。代码风格乱的人哪怕每题都写了也很难让面试官相信他能在团队里协作。我个人在实际操作中还有一个习惯每做完一套卷子我会把错题整理成一个表格左边是题目考点右边是我错误的原因以及对应的正确思路。这种复盘方式不需要很复杂但坚持一个月你会明显发现自己对知识点的理解从“听过”变成了“能讲”。临到面试前再翻一遍这个表比重新看一遍书要有用得多。这里也建议你不管你选哪套题练手考完一定要回头整理这个动作比刷题本身更重要。
返回列表