ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

小红书Android岗第三批笔试复盘:题型、算法与避坑指南

小红书Android岗第三批笔试复盘:题型、算法与避坑指南 2023年秋招我投了小红书的Android开发岗。第三批笔试安排在9月中旬和很多公司的海笔不同小红书的笔试更像一次综合能力体检基础题、设计题、编程题混在一起题量不小时间却很紧。更关键的是这套题不是单纯刷LeetCode就能应付的它既考算法功底也考Android系统机制和工程素养甚至还会在你意想不到的细节里埋坑。这篇文章就把我参加第三批笔试的经验整理一遍从题型、知识点、编程题思路到笔试环境准备希望给后面投递Android岗的朋友一份能直接参考的复盘材料。1. 笔试全景小红书Android岗第三批笔试到底在考什么1.1 这批笔试的整体定位与考察逻辑先说我的整体判断小红书Android开发岗的笔试不是单纯筛代码能力而是在筛“能不能直接上手干活”的人。第三批笔试题目范围覆盖得很广大致分为三块计算机基础与Android核心机制、工程架构与性能优化、算法编程题。前两块通过选择题、填空题、简答题出现最后一块则是经典的在线OJ编程题。这种结构其实很聪明。Android岗如果只考算法容易招到“刷题机器”但不会处理线程、不会排查内存泄漏落地项目时非常痛苦。如果只考Android知识又没办法在笔试阶段用统一标准评估候选人的逻辑思维。所以小红书把两者揉在一起选择题里埋几个边界条件很刁的Java问题简答题直接给一个业务场景让你设计技术方案编程题再考一个不偏不怪但需要仔细处理的算法题。三轮下来真正的基础水平、工程经验、代码习惯基本都能暴露出来。第三批和第一批、第二批的区别我个人的体感是第三批更偏向“当前业务常用的技术栈”例如Jetpack MVVM体系、协程、混淆与多版本适配。如果你只准备了传统四大组件和Handler大概率会在后半部分选择题上吃亏。这一点后面我会展开讲。1.2 题目类型与时间分配建议我遇到的笔试时长是120分钟总共大约30道题。具体分值我记不全但大致比例可以给一个参考题型数量建议时间单选题10-1525分钟多选题5-815分钟判断题/填空题3-510分钟简答/设计题2-320分钟编程题2道50分钟这个时间分配非常关键。很多人一上来就在选择题里死磕结果编程题只剩20分钟心态直接崩了。我当时的策略是先花5分钟把所有题扫一遍把编程题和设计题的难度排个序然后从高性价比的选择题开始快速推进遇到卡壳的先标记跳过最后集中火力处理编程题。还有一个容易忽略的点在线笔试系统左侧有题目列表但很多人不会先去点开编程题看输入输出格式。我建议开考后先点开编程题读一遍题目哪怕不立刻写大脑也会在后台自动开始“预编译”等你做到后面时思路往往已经成形了。这个技巧帮我节省了不少思考时间。2. Android核心技术考察点拆解2.1 四大组件与启动流程从Activity到AMSAndroid基础部分几乎是必考但小红书出题角度比普通八股文更细。比如考Activity启动流程时不会只问你“onCreate和onStart谁先调用”而是给你一段代码问你跨进程启动Activity时AMS、ApplicationThread、ActivityThread之间的消息流转过程或者在特定flag组合下生命周期会怎么变化。这里有一个高频考点Activity的启动模式。我那次笔试里就有一道选择题四个选项分别描述standard、singleTop、singleTask、singleInstance在特定场景下的行为。很多人只记结论比如“singleTop如果栈顶复用就调onNewIntent”但题目偏偏设计成当前栈是A-B-C再用singleTop启动CC会不会出栈我告诉你答案是会因为C本来就在栈顶直接复用onNewIntent会被调用。如果启动的是B则不会复用因为B不在栈顶会新创建一个B入栈。这种题很典型靠死记硬背容易掉坑。建议复习时把启动模式、IntentFlag、TaskAffinity放到一起理解最好把Google官方文档里的任务栈图自己画一遍。笔试时如果允许白纸演算可以把栈图画出来正确率会有明显提升。另外AMSActivityManagerService相关的题目也经常出现。它会考察系统级服务在应用进程中的代理方式比如ActivityManager是AMS的客户端代理ApplicationThread是应用进程给AMS的回调接口。这种题难在方向容易记反我建议用一句话概括App往系统发请求走AMS系统往App发通知走ApplicationThread两者都通过Binder完成跨进程通信。2.2 Handler消息机制与主线程模型Handler机制是Android百考不厌的内容小红书也不例外。我印象深的一道题目是主线程Looper死循环为什么不会卡死应用选项里有“因为MessageQueue有消息时阻塞”“因为InputDispatcher会唤醒Looper”“因为主线程CPU时间片不会被抢占”等干扰项非常像样。正确的理解是Looper.loop()是一个for循环不断从MessageQueue里取消息。当消息队列为空时next()方法会通过epoll机制让线程进入休眠阻塞让出CPU当有事件写入管道时再被唤醒。这个阻塞不是忙等不会造成CPU空转所以主线程的“死循环”不会让系统卡死反而让应用能够持续响应事件。笔试还可能会考Handler的创建方式。很多人在Java层只知道new Handler()在子线程会报错但不知道为什么。其实在Android 11以下如果你在子线程直接new Handler()而没有先Looper.prepare()会抛出“Cant create handler inside thread that has not called Looper.prepare()”异常。Kotlin协程普及之后这类题目比例有所下降但仍是基础题里的稳定成员。建议复习时亲手写一个HandlerThread示例模拟子线程间通信理解Looper和Handler之间的绑定关系。我秋招前自己整理了一张基于Handler的流程图虽然没有在笔试中直接用到但对理解线程模型帮助很大。2.3 Jetpack与MVVM架构笔试中的设计题小红书的业务涉及大量信息流、社区Feed场景客户端代码规模很大所以架构设计能力是笔试考察重头。第三批笔试里简答题就出现了“如果让你设计一个支持多Tab新闻客户端的首页模块你会怎么设计数据层和UI层”这类题目。这种题没有标准答案但阅卷人会快速判断你有没有真正的工程经验。我当时的答题思路是围绕MVVM架构展开ViewModel持有LiveData或StateFlow承载UI状态Repository负责从网络/数据库获取数据Activity/Fragment只做数据观察和渲染通过DataBinding或ViewBinding减少样板代码。同时补充了Paging3处理分页避免一次性加载大量数据造成内存抖动。另外笔试选择题里还考了Room和SharedPreferences的区别以及为什么大厂开始推广Room替代SQLite原生API。这里有一个容易忽略的点Room强制你在编译期写SQL如果表名或字段名写错编译直接报错而原生SQLite运行时才暴露问题。这种“编译期检查”的特性和“LiveData自动感知生命周期”放在一起在大规模团队协作时非常加分。如果你没有系统用过ViewModel建议动手写一个简单的计数器Demo分别用Java和Kotlin实现一遍。重点观察屏幕旋转后数据是否保留理解ViewModel的生命周期为什么比Activity更长。理解了这一点简答题里关于内存泄漏和配置变更的坑就能避开大半。2.4 性能优化与R8混淆容易被忽略的工程素养小红书Android笔试里性能优化题目占比不低而且角度很实际。比如问“线上App如何监控页面卡顿”选项里包括Choreographer.FrameCallback、BlockCanary、MethodTrace、Systrace等正确答案经常是组合选项。这提醒我们只知道单个工具名没用得知道每个工具在哪个阶段用。另一个高频点是ANR。判断题里会出现“BroadcastReceiver中执行耗时操作不一定会触发ANR”这种反直觉描述。实际上广播接收器在主线程执行时长超过10秒不同版本阈值不同就可能弹ANR但在子线程中goAsync()并处理耗时逻辑可以规避。类似知识点靠刷题能记住但如果平时有排查经验理解会更深刻。R8混淆这块是我最想提醒大家的。笔试里有一道多选题关于R8与ProGuard的正确说法。选项里有“R8同时负责压缩、优化、混淆”“R8只支持AGP 3.4及以上版本”“启用R8后不再需要保留规则”“可以通过-keep规则保留特定类不被混淆”。正确答案是前两个和最后一个。很多人只熟悉ProGuard不知道从AGP 3.4开始R8被设置为默认的代码缩减工具到AGP 8.0时ProGuard的支持已经被大幅弱化。这让我想起今年遇到的一个环境坑Android Studio Hedgehog | 2023.1.1 Patch 2这个版本默认会引导项目使用AGP 8.1而AGP 8.x在混淆阶段和旧版org.gradle:gradle插件有兼容问题。如果你习惯在项目中直接用minifyEnabled true旧版混淆规则有不少会被忽略。在笔试中不会考这么细但如果你能在简答题里提到“R8时代需要更新混淆规则并用-printusage、-printseeds输出混淆报告”阅卷人会觉得你有真实上线维护经验。3. 编程题实战真题风格与解题套路3.1 小红书风格算法题的常见类型程序题只考两道但覆盖面很集中。根据我刷题和身边朋友的交流小红书的算法题更看重“边界处理”和“复杂度的合理性”而不是非常偏门的算法。常见类型包括字符串/子串问题比如最长无重复字符子串、字符串匹配变形。数组区间问题比如合并区间、会议室最大重叠数。动态规划通常是背包类、子序列类难度在中等偏上。数据结构模拟比如实现一个LRU Cache。图/树多为基础DFS/BFS较少考到非常复杂的最短路变体。我那一场拿到的是两道题一道是“给定一组区间返回不重叠区间的最大数量”有点像LeetCode 435但要求输出的是最大保留数量而且输入范围偏大必须用贪心排序。另一道是“字符串循环移位后包含目标子串”本质上是字符串匹配但需要O(n)级别解法否则容易超时。这两道题都不是“秒杀题”但也不算冷门。重点在于你能不能快速想到正确思路并把边界条件处理干净。在线OJ对时间复杂度的要求通常比较严格如果上来就写暴力解法小样本能过大样本直接超时得分会很难看。3.2 一道典型题目的完整推导我拿“最长无重复字符子串”这道经典题举例。它经常被当作LeetCode热身题但在笔试里却很容易写错。题目要求给定一个字符串找到其中不含重复字符的最长子串长度。直观做法是枚举所有子串并判断是否包含重复字符时间复杂度O(n^2)。但在笔试环境下字符串长度可能达到10^5暴力必超时。正确做法是滑动窗口fun lengthOfLongestSubstring(s: String): Int { val lastIndex IntArray(128) { -1 } var left 0 var maxLen 0 for (right in s.indices) { val c s[right].code if (lastIndex[c] left) { left lastIndex[c] 1 } lastIndex[c] right maxLen maxLen.coerceAtLeast(right - left 1) } return maxLen }核心逻辑是维护一个“当前窗口”的左边界left当遇到一个已经出现在窗口内的字符时直接把左边界移动到之前该字符出现位置的下一位。因为窗口是连续区间所以不需要删除窗口内旧字符只需要更新左边界即可。lastIndex保存每个字符最近一次出现的下标。这个解法的时间复杂度是O(n)只用了一个固定大小的数组做哈希表空间复杂度O(1)。我在笔试里就用的这个思路但第一版漏了if (lastIndex[c] left)这个条件导致重复字符在窗口外时仍然误判为重复输出结果偏大。这类边界问题最保险的办法是在草稿纸上手动模拟一个短字符串比如“abba”一步步走一遍很多bug能当场暴露。3.3 编程题答题注意事项在线笔试平台和本地IDE有区别代码提交后没有断点调试也没有大量的打印日志权限。我踩过几个很现实的坑整理一下输入输出格式有些平台要求自己写readLine()循环读取有些平台则提前帮你封装了函数你只需要实现方法体。开考第一件事就是搞懂题目给你的模板。main函数与class的关系在笔试平台里如果题目明确让你实现一个Solution类就不要再写独立主类否则编译会报重复类错误。Kotlin空安全写Kotlin时如果题目输入的字符串可能为null要用?和?.let处理直接给非空类型赋值会编译失败。超时输出如果结果很大注意题目是否要求取模我在LeetCode遇到过% 1000000007的题笔试里同样会有。还有一点很容易被忽视在线OJ的代码编辑器自动补全能力很弱甚至没有。如果你平时高度依赖IDEA的自动导包建议考前用记事本手写几道算法的完整代码训练自己在无补全环境下的编码速度。别觉得这是小事笔试环境里少按几次回车的差异会被焦虑放大很多倍。4. 笔试环境和工程准备4.1 Android Studio环境与AGP版本选择虽然笔试是网页在线做题不要求本机安装Android环境但前期刷题和准备项目时Android Studio仍是绕不开的工具。这里我要重点聊聊AGP版本兼容问题尤其是今年以来很多应届生被坑过的事。热词里提到的Android Studio Hedgehog | 2023.1.1 Patch 2这个版本默认推荐AGP 8.1/8.2。如果你机器上装的是新版本Studio却在一个老项目里遇到了Could not load compiled classes for settings file十有八九是AGP版本和Gradle版本不匹配。比如AGP 8.x要求Gradle 8.0以上而项目里还配着7.x的Gradle同步时就会出现很莫名其妙的报错。我建议统一使用官方推荐的版本组合Android Studio Hedgehog配AGP 8.1.0、Gradle 8.0。这样能避开百分之九十的兼容性问题。如果你还在用AGP 7.x的老项目最好不要强行用新版Studio打开可以先把项目升级到AGP 8之后再做功能开发。顺便提一嘴笔试本身不考这个但在简答题里如果聊到“项目工程化”你随口提到“AGP 8去掉了对旧版Transform API的支持建议迁移到ASM或Gradle Transform API的新实现”能立刻和只会说“我用了某某框架”的候选人拉开差距。4.2 手写代码与工程思维的转换笔试中有一类题是“给一段代码找错”这种题特别考验代码阅病能力。我遇到一个例子在子线程中直接更新TextView的文本问会有什么问题以及如何修复。答案是抛CalledFromWrongThreadException修复方式是通过runOnUiThread或View.post切换线程。很多人会回答“用Handler”这没有错但不够工程化。真正维护过大型项目的人会补充可以用ViewModel LiveData把数据从子线程更新到ViewModel由主线程的LiveData观察到后再更新UI。这个回答能把“基础题”上升到“架构题”阅卷人自然更愿意给高分。类似的还有一道“如何监听手机通话状态”的设计题。这里要避开一个坑直接注册PhoneStateListener在Android 12以上已经越来越受限不如用TelephonyCallback。如果你不知道新API至少要在答案里说明动态权限检查和回调注册时机。这些细节展现的是“你关注过平台演进”而不是“只会在网上抄代码”。4.3 项目经验如何体现在笔试中简答题没有标准答案但非常适合把项目经验包装进去。比如问“如何优化一个列表卡顿”你可以从四层来说数据层用分页缓存业务层用协程控制线程调度UI层用RecyclerView复用DiffUtil监控层用BlockCanary做卡顿检测。如果只是笼统回答“异步加载”“ViewHolder复用”得分空间就很有限。我在笔试中关于“动态图标主题”和“协调布局Banner”的题目也遇到过不过不是完整设计题而是选择题。动态图标主题其实涉及资源系统里dayNight主题切换和DynamicColor在Android 12上可以实现基于壁纸的动态取色。协调布局搭配Banner则主要考察AppBarLayout的滚动行为和CollapsingToolbarLayout的折叠效果。这种题只要平时真的做过布局一看选项就知道答案。所以说简历里写的项目不要只写“参与开发”笔试考官非常擅长从简答题细节里判断你有没有碰过真实代码。哪怕是一个简单的Banner轮播框架如果你能说出ViewPager2的RecyclerView复用机制和旧版ViewPager在滑动冲突上的区别就能比别人多拿分。5. 避坑指南笔试现场与常见问题速查5.1 时间不够用怎么办我第三批笔试时有个特别直接的感受前面的选择题比想象中更耗时间。尤其是多选题少选、漏选、错选都有不同扣分规则逼着人反复斟酌。如果前30分钟发现自己才做了8道题后面就必须做一次“取舍”。我的建议是多选题里对某个选项不确定尽量按“选自己最有把握的”来不要冒险全选。编程题相对分值更高而且只要通过部分测试用例就能拿部分分所以绝对不能空着。就算最后没有完整思路也要写下暴力解法拼一个通过率这比交白卷强太多。另外很多在线笔试系统会自动保存答案但页面上可能没有明显提示。我习惯每做完10道题就刷新一下页面看看答案是否还在虽然这个操作有点强迫症但能避免浏览器意外关闭时的心跳骤停。5.2 环境异常与提交失败处理在线笔试最怕遇到网络抖动或编辑器卡死。我周围就有同学因为突然断网导致代码编辑区无法保存最后被迫重启电脑浪费了20分钟。这里给大家几个实际经验提前用Chrome或Edge关闭所有无关标签页尤其是视频网站、音乐播放器。如果编辑器卡顿不要反复点击先等10秒仍然无响应再刷新页面。提交代码后如果长时间显示“判题中”尽量别反复点提交按钮容易导致重复提交部分平台会按最后一次提交来计分。对时间复杂度没有信心的题目可以在代码注释里简略写自己的思路有些人工阅卷会看注释给分。还有一件很细节的事部分平台支持本地IDE编写后粘贴代码这时候要注意代码缩进是否被转化为空格。Kotlin代码稍微改变缩进不影响编译但Python类答案可能会被缩进搞崩。既然考的是Android岗多使用Kotlin或Java不要冒险用Python写法应对。5.3 常见知识点容易混淆的坑最后整理一个我在复习和笔试中反复踩的高频易混淆点直接做成速查表知识点常见误区正确理解Activity启动模式singleTop只会复用栈顶Activity只有当目标Activity已在栈顶时才复用否则仍会新建实例Handler子线程new Handler前必须手动prepare主线程有默认Looper子线程需要主动初始化LiveData它会自动把数据发到子线程只能在主线程setValuepostValue才能在子线程调用并从主线程回调ViewModel它拥有比Application更长的生命周期ViewModel只有在Activity/Fragment销毁时才清空不会跨进程存活R8它等于ProGuard的替代品R8是同时做压缩、优化、混淆的工具从AGP 3.4起默认启用FileProvider可以通过file://暴露文件给其他应用Android 7.0以上必须使用content://协议共享文件否则抛FileUriExposedException蓝牙通信Android 12以上无需动态申请权限需要申请BLUETOOTH_SCAN、BLUETOOTH_CONNECT等多个运行时权限系统OTAOTA只改系统应用不影响普通应用OTA会触发应用私有目录、权限模型变化应用需要做兼容性测试这张表里每一项我在笔试里都见过至少一种变体。尤其是FileProvider的content://协议题干中会出现类似content://com.baidu.searchbox.fileprovider/baiddpath/android/data/...这样的内容问你该URI是否能被其他应用直接访问。答案是不行原因在于跨应用共享文件时需要临时授权给接收方而不是单纯拼接路径。这种题非常实际也正好是日常开发中容易埋雷的地方。另外Android 14以后部分权限和隐式Intent规则又加严了大家在复习时最好以最新的官方行为基线为准不要抱着旧版系统习惯死磕。写在最后第三批笔试过后我最大的感受是真正的差距不在“会不会某个API”而在“遇到一个不熟悉的问题时能不能用已知的知识推演出合理方案”。小红书这套笔试题目把这一点体现得很彻底从AMS到R8从算法题到架构设计每一个环节都在逼你用工程视角思考问题。我个人复盘时觉得最有用的一个动作是把所有错题都按“题干陷阱”“知识点模糊”“代码习惯问题”三类打标签。比如“判断R8用法”这道题我错在把ProGuard旧规则直接套给了R8再比如“Activity启动模式合并场景”那道题我错在只记得结论、没有画栈图。把这些标签梳理完以后再去看后面的面试题方向清晰了很多。如果你也正在准备Android开发岗秋招最后再分享一个小技巧笔试前三天不要刷太多新题把旧题里的边界条件、时间复杂度和代码规范重新过一遍比新做十道题更有用。小红书第三批笔试给我的感觉就是它不期待你背住多少偏题怪题而是看你在有限时间内能不能写出稳定、正确、有工程味道的答案。能做成这一步笔试就成功了一大半。
返回列表