小红书Android秋招笔试复盘:四大模块核心考点与避坑策略
小红书2023秋招Android开发岗第一批笔试我当时排在9月初那场整体做下来最大的感受是题目不算偏但覆盖面很广Android基础、JVM/Kotlin、算法、系统框架都有涉及。它不像社招那样深挖某个源码细节更看重你把一个知识点讲明白、讲系统。这篇文章我把整场笔试的复盘整理出来从题型结构、核心考点、答题策略到踩坑记录给正在准备Android校招的同学一份可以照着准备的清单。我当时投递的是Android开发工程师客户端方向笔试时间120分钟整体题量偏大如果前面选择题犹豫太久后面算法题会很赶。所以这篇复盘不只是罗列知识点我会把每个考点对应的得分策略、常见的问法陷阱、以及平时复习容易遗漏的地方一起说清楚。1. 笔试基本盘题型、考察范围与考前优先级1.1 题型构成与考察范围先说我拿到的这套题的构成大致分四块选择题单选多选约20-25道覆盖Java/Kotlin基础、Android四大组件、Handler、多线程、集合框架、网络协议、数据结构。算法题2道LeetCode中等偏上难度一道偏字符串/数组操作一道偏二叉树或动态规划。简答/设计题1-2道考某个组件的工作原理或者给你一个场景让你设计实现方案。附加题不一定有部分批次的题目里会有开放性题目比如让你设计一个图片加载库、分析卡顿问题。从考察范围看它基本覆盖了校招Android岗笔试的大部分标准模块。我在备课时按权重排了优先级Java/Kotlin语言基础 四大组件与Handler 并发与线程 算法 Jetpack与架构 性能优化 源码原理。这篇帖子的重点会放在Android相关内容上。1.2 考前优先级怎么排笔试不是面试没有追问环节所以你的答案必须在一个题目的有限篇幅里让对方看到你知道的边界。我排优先级主要看两个维度被考到的概率、以及投入产出比。Java集合与并发是性价比最高的部分ArrayList/HashMap/HashSet的底层原理、HashMap在并发下的问题、线程池参数、synchronized与volatile的区别这些都是高频中的高频。Android部分Activity启动流程、Handler机制、事件分发、Binder原理是必考而且笔试中经常以选择题形式出现不需要你手写源码但必须理解过程。算法题我的建议是至少把LeetCode Hot 100刷两遍。小红书这批笔试的算法题不偏基本没出冷门题型但题量不小熟练度直接决定你能不能做完。1.3 关于时间分配的总体计划拿到试卷后我用了5分钟快速浏览全部题目把每道题预计耗时标了一下。选择题控制在45分钟内完成算法题留60分钟简答题留15分钟。这样做的原因是选择题里有很多一眼能看出答案的基础题纠结两三道难题不如用这个时间保证算法题能完整跑通。实际操作中我最后多选和简答用了相对少的时间算法第二道快结束时有些赶这也是这次笔试的一个小遗憾。2. Android核心基础启动流程、消息驱动与生命周期2.1 Activity启动流程与AMS的协作逻辑这套题里关于Activity启动流程出现了至少两处一道选择题问startActivity之后系统做了什么一道简答让简述整个过程。这类题能否得分关键在于你能不能把Launcher进程、SystemServer进程、App进程的角色分清楚。完整流程可以按这条线记调用startActivity后实际会经过ActivityManagerShellCommand或应用内的ActivityTaskManager.getService()通过Binder调用到系统进程里的ActivityTaskManagerService再通知AMS做权限校验、任务栈调整、进程创建和生命周期调度。笔试作答时我建议分成三层来说应用内发起startActivity - Instrumentation.execStartActivity - ActivityTaskManager.getService().startActivity这里涉及Binder IPC。系统进程处理ATMS/AMS完成ActivityRecord创建、栈管理、Intent解析、权限检查并决定要不要创建新进程。进程与生命周期回调如果目标Activity所在进程不存在通过Zygote fork新进程然后Application创建、Activity创建、onCreate/onStart/onResume按顺序回调。答题时容易漏掉的点有两个一是新进程的创建是请求Zygote完成的AMS本身不直接fork二是onResume回调是在进程创建完成后由系统进程通过Binder反向调用进应用进程的。这两个点写出来能让你的答案明显超过背过流程的水平。2.2 Handler消息机制Looper为什么必须prepareHandler这套题在笔试里出现的频率稳定得可怕。选择、填空、简答都有可能。它考的不只是API而是理解消息驱动模型。消息机制的核心角色是MessageQueue、Looper、Handler三者。Looper通过MessageQueue不断取消息Handler负责发送消息和处理消息。笔试常考的一个点是为什么在使用Handler之前必须调用Looper.prepare()这个答案的关键在于Looper是一个ThreadLocal变量每个线程只能有一个Looper实例而prepare方法会把当前线程初始化为带Looper的线程。主线程在ActivityThread的main方法里已经预调用了Looper.prepareMainLooper()所以你直接new Handler就行子线程则需要自己prepare和loop。还有一个容易失分的方向是同步/异步消息和消息屏障。笔试多选题如果出现关于Handler机制说法正确的是经常会在这些选项里埋雷MessageQueue的next()方法会阻塞、IdleHandler用于空闲时处理任务、SyncBarrier可以屏蔽同步消息这些都是需要掌握的细节。2.3 四大组件生命周期与进程优先级除了ActivityService、BroadcastReceiver、ContentProvider也各有一两道题。Service主要考startService与bindService两种启动方式的区别以及onStartCommand的返回值含义。BroadcastReceiver考静态注册与动态注册的区别、Android 8.0后静态注册隐式广播的限制。ContentProvider考的基本是它和Binder的关系以及ContentResolver作为统一入口的意义。这里有个容易忽略的考点进程优先级。系统在内存不足时会按优先级杀进程从高到低依次是前台进程、可见进程、服务进程、后台进程、空进程。问你哪个进程最不可能被杀这种选择题基本都围绕这个优先级展开。生命周期部分设备旋转导致的Activity重建是一个经典问法通常紧接着会问ViewModel为什么能在旋转后存活。这里要联系到ViewModelStore和NonConfigurationInstances的关系单纯背生命周期表格是不够的笔试会把多个知识点串起来考。3. Kotlin协程与Jetpack架构笔试里的新势力3.1 协程的挂起与恢复怎么答才不丢分近两年校招笔试中Kotlin协程的出现频率明显上升。选择题的方式通常是让你判断几个协程代码片段的执行顺序或最终结果。简答则会让你讲讲协程与线程的关系、为什么协程能挂起而不阻塞。挂起的本质是协程体被编译成一个状态机遇到挂起函数时当前协程的执行状态和局部变量被保存线程资源释放等异步结果准备好后在指定调度器上恢复执行。笔试作答时把这几层讲清楚就行协程依赖的Continuation、状态机机制、以及Dispatchers决定在哪个线程上执行。setOfDispatchers这块有一个高频易错点withContext(Dispatchers.IO)里执行耗时任务、然后回到Dispatchers.Main更新UI这是标准写法。考协程作用域时题目经常给一段代码问你哪里有问题常见埋坑是全局作用域里启动协程做UI操作导致内存泄漏正确做法是用ViewModelScope或lifecycleScope。3.2 MVVM与ViewModel的考察方式笔记热词里有android studio mvvm代码示例说明现在面试官默认候选人懂MVVM。笔试这边它通常结合生命周期来考不会让你写完整代码但会给你一段ViewModel代码判断问题。ViewModel能做Activity重建时的数据存活是因为它在配置变更时不会跟着Activity销毁系统会通过NonConfigurationInstances把ViewModelStore保留下来。这一点我上一章提到过用的就是这个考点。MVVM这块还常考ViewModel与LiveData/Flow的配合以及DataBinding的作用。笔试作答时不需要展开DataBinding的具体API但要能说清楚MVVM三层各自职责View负责渲染和事件收集ViewModel负责业务逻辑状态Model负责数据来源。以及单向数据流为什么能减少状态不同步的问题。3.3 设计题实战写法图片加载框架怎么答如果笔试出现开放设计题高频题目大概率是让你设计图片加载框架或者网络层框架。我当时遇到的是图片加载框架这种题没有标准答案但阅卷人能从你的方案里看出是否真的接触过工程实践。我当时的作答结构是这样的总体分层API入口层load/into - 调度层线程池任务队列 - 缓存层内存缓存磁盘缓存 - 网络层下载图片 - 解码层BitmapFactory/ImageDecoder。缓存策略LruCache做内存缓存DiskLruCache做磁盘缓存key用URL hash。这里要说明为什么用LruCacheLinkedHashMap实现LRUAndroid系统原生支持。线程模型主线程发任务IO线程执行下载和磁盘读取解码跑在非主线程回调切回主线程。易扩展点支持自定义解码器、支持渐进式加载、支持生命周期感知在Fragment销毁时取消请求。这样的方案结构完整同时向阅卷人展示了你对图片加载链路的理解。任何类似设计题都可以套这个思路入口 - 调度 - 缓存 - 执行 - 回调。4. 性能优化与工程化从ANR、内存到R8混淆4.1 ANR问题笔试中的高频场景题ANR这样的题虽然不会让你真的去抓一份trace文件但会给场景判断哪些操作可能导致ANR。我记得热词里有android 测试和android frameworkANR正好是这两者的交叉点。ANR的触发场景笔试常考的是四类输入事件5秒未响应、BroadcastReceiver前台10秒/后台60秒未执行完、Service前台20秒/后台200秒未执行完、ContentProvider在发布过程中超时。考法通常是这样给一段代码问为什么会导致ANR或者给你一个卡顿问题让你说出排查思路。回答的切入点就围绕主线程是否有耗时操作展开。最容易错的选项是在onCreate里做网络请求这种它不一定立刻ANR但如果超过5秒就会。所以答题时要强调ANR的判定是超时机制不是某个操作本身违规。排查思路题则需要你像真实开发那样回答先看/data/anr/目录下的traces.txt再看主线程堆栈和CPU占用结合logcat看是否有死锁或广播阻塞。这套思路笔试能写出来说明你有实际排查过问题。4.2 内存泄漏与卡顿优化内存泄漏题在笔试中经常以以下哪些会造成内存泄漏的形式出现。经典陷阱包括非静态内部类持有外部Activity引用Handler就是典型、静态变量引用Activity、匿名内部类做成异步任务后Activity销毁、单例持有Context、流未关闭。作答的时候别只背结论最好能补一句为什么会泄漏。比如Handler泄漏是因为主线程的Looper持有MessageQueueMessageQueue里有待处理的消息Message的target指向Handler而Handler是Activity的内部类实例隐式持有Activity引用。这条引用链导致Activity无法被回收。笔试里能写出引用链这道题的答案质量会明显不一样。卡顿优化题一般是问你怎么定位掉帧。我的思路是利用Systrace或Perfetto抓trace看主线程执行时间线再结合布局层级减少嵌套、使用ConstraintLayout、避免在onDraw里创建对象、减少过度绘制几个层面回答。4.3 R8与代码混淆笔试里的隐藏加分项针对热词里出现的android r8和android 马甲包代码混淆说明混淆相关问题是这两年笔试的新增关注点。它会问R8与ProGuard的区别这题不难但很多人答不好。R8是AGP 3.4以后默认的代码压缩与混淆工具它把ProGuard的压缩、优化、混淆、脱敏四个步骤合到了一起整体更快。笔试作答时说清楚R8包含的四个职能就够了shrink删除无用代码和资源、optimize字节码级优化、obfuscate类名/方法名混淆、preverify预校验。另外一个常见考法是给一个keep规则让你判断某个类能不能被混淆。核心是记住keep规则的含义-keep表示保留类和成员不混淆、-keepclassmembers保留类成员、-keepnames只保留原名不参与重命名。要注意的是keep规则会保留大量代码不利于压缩所以不要滥用。4.4 AGP版本与构建工具链笔试的一个冷门题方向是构建链路比如问你Android Gradle PluginAGP和Gradle版本的关系。热词里那串android studio hedgehog | 2023.1.1 patch 2支持agp8版本吗本质上考的就是版本兼容意识。这里不需要准确背出每个版本的兼容矩阵但必须知道AGP版本和Gradle版本存在对应关系AGP 8.x需要Gradle 8.0以上升级Android Studio后旧项目有时候要同步升级AGPAGP 8.0移除了很多旧API使用了transform API的三方库会不能编译。笔试如果出这种题通常是给你一组组合让你判断是否合法。作答技巧是记一条主线Android Studio大版本发布时会默认配套一个AGP版本升级Studio时先看项目的AGP是否需要同步升级。这个问题实战价值很高因为秋季校招很多同学拿自己电脑上现成的项目去笔试构建环境不一致就会浪费时间。5. 做题实战算法、开放题与时间分配策略5.1 算法题的三个手写陷阱笔试的算法题不是让你白板写完整可运行代码但判题系统会看核心逻辑。我这次遇到的两道题都不难但有两个地方差点丢分。第一个是边界条件。比如字符串处理题里空字符串、单个字符、全相同字符这些Case如果你没有在编码前想清楚很容易写出if条件不全的代码。建议养成习惯拿到题先花30秒列出边界情况再写代码。第二个是复杂度的把控做题时标注清楚时间和空间复杂度这是加分项。第三个是不要用IDE的自动补全和格式化功能笔试环境有时候没有补全平时就要练手写代码的能力。5.2 开放题怎么答才像有经验的人开放设计题不需要你写出完整实现重点是展现你的工程视角。我建议用总分结构回答先一句话说明整体方案再分模块描述每个模块写明职责和关键实现最后说不足和可扩展性。还是以图片加载框架为例开头概括整体采用三级缓存线程池调度生命周期感知架构。然后分别写内存缓存、磁盘缓存、网络层、解码层的职责。结尾加上一句如果后续要支持视频封面加载可以在解码层做扩展这种写法说明你考虑过框架的演进方向。阅卷人看到这种答案容易和背题背出来的人区分开背题的人只会列组件名有经验的人会写组件间的交互和取舍。5.3 做题检查清单交卷前一定要看的三件事我习惯预留最后5分钟做检查主要看三件事选择题是否勾选了所有题目多选有没有少选多选少选有时按比例给分空着必然零分。算法题代码是否考虑了空输入和非法输入方法签名是否跟题目要求一致。简答题的关键术语是否写对比如ActivityThread、Instrumentation、Binder这些词不能拼错。这三件事花不了几分钟但每年都有人因为漏选、签名不一致和拼写错误丢分。6. 踩坑记录与秋招笔试速查表6.1 我踩过的几个典型坑第一个坑是选择题的时间没控制好。我在一道关于HashMap并发问题的多选题上纠结太久导致后面算法时间被压缩。复盘反思笔试里遇到拿不准的题可以先标记做完后面的题再回来想而不是卡在原地。第二个坑是Kotlin协程代码分析题。给出了一段包含delay、withContext、async的代码问最终输出顺序。我在是否切回主线程的问题上判断失误。这类题的关键是记住async await在同一个上下文中执行时依旧可以并发但结果收集是顺序的withContext不会新开协程只切换调度器。平时多跑几段这种代码比单纯背结论更有用。第三个坑是环境准备。我用的开发机AGP版本和线上笔试环境不一致编译报错浪费了不少时间。笔试前一定确认自己的Gradle、AGP、Android Studio版本能正常同步并且提前测试白板代码环境别等到开考才发现环境不对。6.2 笔试常见问题速查表问题类型关键点易错提醒Activity启动流程ATMS/AMS、Zygote、Binder别忘记进程创建由Zygote完成Handler机制Looper.prepare、ThreadLocal子线程需要手动prepare/loopService启动方式startService与bindServiceonStartCommand返回值含义进程优先级前台可见服务后台空记住服务进程在后台进程前HashMap并发死循环、数据丢失Java 8后改用红黑树并发仍不安全协程挂起状态机、Continuation挂起不阻塞线程MVVM单向数据流、ViewModelStore数据状态由ViewModel持有ANR输入5秒、广播前台10秒主线程耗时是根因R8shrink/optimize/obfuscatekeep规则不要滥用AGP与Gradle版本要匹配AGP 8需Gradle 8内存泄漏Handler泄漏、静态引用引用链要能讲清事件分发dispatchTouchEvent返回true消费分清三个方法职责Binder一次拷贝、MMAP区别于传统IPC两次拷贝图片加载设计分层缓存线程调度别忘了生命周期感知ContentProvider跨进程、BindernotifyChange观察者机制6.3 给你的最后建议笔试只是秋招长跑中的一站真正决定你走多远的是能不能持续把基础概念讲清楚。我在备考那段时间最大的体会是把每个知识点用自己的话写一遍比刷十篇面经更有效。面经给你的是题目而你能不能在笔试现场准确输出取决于你对原理的理解深度。如果你这周就要上考场建议按这个顺序突击先把四大组件、Handler、Binder这三个Android基石过一遍把Java集合和并发的选择题刷一遍再把LeetCode Hot 100里字符串和二叉树题过一遍。这三个模块占掉笔试60%以上的分数优先拿稳它们再去看R8、AGP、协程这些加分项。最后分享一个小技巧笔试前可以自己给自己做一次限时模拟卡着120分钟做一套综合题让自己适应边做题边标记不确定题目的节奏。这个习惯帮我稳住了很多本来会慌的场面。祝各位秋招顺利。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →