
这套卷三是我整理校招笔试题时印象最深的一套。原因倒不是它有多难而是它的出题逻辑特别“实”——几乎每一道题都能在真实的Android开发场景里找到对应位置没有那种背八股就能拿分的纯记忆题。小红书作为内容社区类App对候选人的考察明显偏向信息流场景下的性能、稳定性和架构能力这一点从卷三的题目分布上能看得很清楚。这篇复盘我会按照卷面结构逐题拆开把每道题背后的考点、破题思路、常见错误都过一遍。如果你正在准备Android校招或者工作两三年想查漏补缺这篇应该能帮你在刷题时少走不少弯路。1. 卷三的定位与整体复盘这套卷子到底在考什么先说结论小红书的校招笔试并不是单一难度阶梯而是“基础层 进阶层 业务开放层”三段式结构。卷一、卷二通常用来筛掉基本功不扎实的候选人到了卷三出题人开始考察你有没有形成自己的工程判断力——也就是说答案本身不是最重要的重要的是你选择方案时的理由。1.1 卷三在整套笔试中的位置根据那几年校招笔试的普遍规律卷一、卷二以Java基础、Android四大组件、网络协议这些“题库型”题目为主靠刷题可以拿高分。但卷三明显换了风格纯选择题比例降低简答题和场景设计题占比上升还出现了一些需要结合实际开发经验才能答好的开放题。这说明什么说明到了卷三这个环节面试官默认你已经具备基本知识储备开始考察你的技术决策能力——同样一个功能你用方案A不用方案B理由是什么你踩过什么坑这些坑能不能总结成方法论1.2 知识点分布与难度梯队我按记忆把卷三的知识点分布做了个整理大概是这个比例知识模块占比主要考察方向Java/Kotlin基础15%集合、字符串、并发、内存模型Android核心机制30%Handler、生命周期、Binder、AMSView体系与交互20%测量、绘制、事件分发、滑动冲突性能优化与稳定性20%ANR、内存泄漏、启动速度、包体积架构与业务设计15%MVP/MVVM、组件化、信息流场景整体难度是递增的。前面基础题只要复习过都能答但从View体系开始没真正写过自定义View、没处理过线上问题的候选人会明显感到吃力。开放题更是如此不是靠背题能解决的。1.3 答题时间与策略参考那场笔试的时长大概是120分钟我个人建议的分配是选择题20分钟内搞定不要犹豫简答题控制在70分钟每题先写核心要点再补细节开放题留30分钟以上因为这类题最拉分很多人最后没时间写非常可惜。还有一个特别重要的技巧宁愿字迹潦草写完整也不要字迹工整写一半。面试官看的是你的思路完整性不是你的书法。简答题如果实在不会把能想到的关键词、公式、流程都写上去多少能拿点分。2. Java与Android基础层程序员的“肌肉记忆”题这一部分对科班出身的人来说属于送分题但对于跨专业或者基础不牢的候选人反而是丢分重灾区。原因很朴素这些知识点太平常了平常到很多人用过就忘真让你说出原理又说不太清楚。2.1 HashMap的线程安全与扩容问题卷三出了一道关于HashMap的简答题大意是在多线程环境下往HashMap里put数据会发生什么如何解决这道题的考点有三个层级。第一层是知道HashMap不是线程安全的第二层是能说清楚为什么不安全——resize扩容时如果多个线程同时检测到需要扩容会各自创建新的数组然后互相覆盖甚至在高并发下形成循环链表get时死循环第三层是能给出解决方案。解决方案本身不复杂用ConcurrentHashMap替代或者用Collections.synchronizedMap包装。但这里有个容易踩坑的点很多人只知道ConcurrentHashMap线程安全却说不清它的实现机制。面试官顺着问下去如果连volatile和CAS都说不出来那就露馅了。正确的答题姿势是这样的先说明HashMap底层是数组链表红黑树JDK 1.8之后再提扩容阈值是负载因子0.75然后说清多线程覆盖和死循环的成因最后落到ConcurrentHashMap的锁分段或CASsynchronized实现。这样一条线下来既展示了知识广度也展示了深度。2.2 字符串拼接的性能与内存陷阱这道题很经典在循环里用拼接字符串和用StringBuilder性能差距有多大答案当然是StringBuilder快得多但关键在于你得说清楚为什么。String是不可变对象每次用拼接都会创建一个新的String对象这个过程中还会产生中间状态的char数组副本。循环次数越多临时对象越多GC压力越大。如果是在主线程拼接大量日志字符串甚至会引起掉帧。但这里有个细节很多人不知道现代Java编译器会在编译期对做优化——如果拼接表达式是常量编译期就会完成如果是在循环里动态拼接编译器会把转成StringBuilder.append调用。所以严格来说单次拼接和循环内拼接的情况不一样。不过笔试阶段不需要抠这么细重点还是答出String不可变、频繁创建对象、StringBuilder可变缓冲区这三个要点。2.3 Activity生命周期与Fragment重叠问题生命周期是Android面试的常青树卷三当然不会放过。它考的角度比较刁屏幕旋转时Activity和Fragment分别经历了哪些生命周期回调为什么会出现Fragment重叠怎么解决先说生命周期。屏幕旋转时Activity会经历onPause - onStop - onDestroy - onCreate - onStart - onResume注意是重建不是简单的暂停恢复。Fragment的生命周期会跟随宿主Activity变化而且在这个重建过程中Fragment会被保存然后重新创建。Fragment重叠这个坑我当年帮人排查过很多次。典型场景是异步请求回来后add了一个Fragment结果屏幕一旋转出现了两个一样的Fragment。原因在于系统重建Activity时会自动恢复FragmentManager里保存的Fragment实例如果你在onCreate里又无条件地add一次就叠加了。解决方案很统一加一个判空条件if (savedInstanceState null)才执行add。这个简单判断背后是对Activity重建机制的深入理解也是面试官希望看到的答题思路。2.4 Handler消息机制主线程为什么不会卡死这道题几乎是Android面试的必考题卷三也有一道相关的简答题主线程的Looper是一个死循环为什么不会导致App卡死ANR又是怎么触发的想拿到这道题的分数要让面试官感受到你是真懂而不是背了标准答案。用大白话拆解一下Handler的本质是向MessageQueue里投递消息Looper负责从队列里取出消息并分发给target处理。主线程Looper确实是一个for(;;)死循环但阻塞点在MessageQueue.next()里的nativePollOnce。这个native方法使用的是Linux的epoll机制——没有消息时线程会休眠不占CPU有新消息时通过pipe管道唤醒线程。所以“死循环”实际上是一个有事件才工作、没事件就挂起的消息泵它不会耗尽CPU更不会让App无响应。真正的ANR是什么是某个消息在主线程处理时间超过阈值——输入事件5秒、广播10秒、前台Service 20秒。主线程被一个耗时操作卡住了队列后面的消息处理不了才会触发系统弹ANR。答这道题其实还有一个加分项说出IdleHandler。它是在消息队列空闲时执行的回调可以用来做启动优化时懒加载非核心操作。这能说明你不仅懂原理还知道怎么利用原理优化性能是很打动面试官的一个点。2.5 Service两种启动方式与后台限制下的选择谈Service的题在现在的校招笔试题里越来越偏实际了。卷三问的是startService和bindService的区别是什么如果应用处于后台还能随便起Service吗这两种启动方式的核心区别可以列个表对比项startServicebindService生命周期独立start后与调用者无关与绑定方绑定解绑则销毁通信方式通过Intent传参单向通过IBinder接口双向调用典型场景下载、播放音乐音乐播放时UI控制、获取数据销毁方式stopService 或 stopSelfunbindService关于后台限制这是个很现实的坑。从Android 8.0开始后台应用不能随意创建后台Service强行创建会抛IllegalStateException。Android 12又进一步限制了前台Service的启动。所以现在做长任务的标准方案是WorkManager它内部会选择合适的时机执行任务并遵守系统的节能策略。笔试如果遇到这类题目我建议先答基础区别再带一句“现在的Android版本对后台Service做了严格限制实际开发中会优先考虑WorkManager或Foreground Service”这样能体现出你关注系统版本演进而不是只会背教科书。3. 绘制与交互自定义View是校招的“分水岭”这一部分是卷三拉开分数差距的地方。说实话很多候选人在准备校招时把精力都放在背面试题上了但View体系这东西真的背不出来——你只有亲手写过自定义View处理过测量和事件冲突才能在笔试中写出让人信服的答案。3.1 MeasureSpec三种模式与wrap_content经典坑卷三这题很稳MeasureSpec由哪两部分组成三种模式分别对应什么场景自定义View时wrap_content有什么坑MeasureSpec是一个32位的int值高2位代表Mode低30位代表Size。三种模式分别是EXACTLY父View已经确定了子View的精确大小通常对应match_parent和wrap_content之外的明确尺寸或者match_parent。AT_MOST子View最大不得超过某个值通常对应wrap_content。UNSPECIFIED父View对子View没有限制可以随便多大一般出现在ScrollView、RecyclerView的items测量中。而最经典的坑是自定义View如果重写了onMeasure当XML里设置wrap_content时默认的resolveSize不会生效View会被当成match_parent处理占满整个父布局。这是个非常隐蔽的bug——很常见的自查逻辑就是“为什么我这自定义控件设置了wrap_content还是撑满了”。解决方案是在onMeasure里手动处理Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode MeasureSpec.getMode(widthMeasureSpec); int widthSize MeasureSpec.getSize(widthMeasureSpec); int resultWidth 0; switch (widthMode) { case MeasureSpec.EXACTLY: resultWidth widthSize; break; case MeasureSpec.AT_MOST: // 计算内容实际需要的宽度取两者最小值 resultWidth Math.min(measuredContentWidth(), widthSize); break; case MeasureSpec.UNSPECIFIED: resultWidth measuredContentWidth(); break; } setMeasuredDimension(resultWidth, ...); }笔试时不需要写完整代码但一定要把这个坑和解决思路说出来。3.2 事件分发的完整链路与滑动冲突事件分发这道题卷三至少占了10分。考点是一次点击事件从产生到最终被消费经过了哪些方法父View和子View如何协同决定谁处理标准的链路是dispatchTouchEvent - onInterceptTouchEvent - onTouchEvent。当手指按下时事件从Activity的dispatchTouchEvent开始一路传递到ViewGroup的dispatchTouchEvent这里会先询问onInterceptTouchEvent要不要拦截不拦截就传给子View子View处理不了就抛回父View的onTouchEvent。这里面最常考的坑是滑动冲突。典型场景一个横向滑动的ViewPager嵌套了一个纵向滑动的RecyclerView或者一个下拉刷新容器里套了一个列表。处理方案有两个方向外部拦截法在父View的onInterceptTouchEvent里判断——如果父View需要滑动就拦截否则不拦截。内部拦截法子View通过requestDisallowInterceptTouchEvent(true)阻止父View拦截事件结合父View的onInterceptTouchEvent里判断!disallowIntercept。笔试答这个题时建议配合手势判定水平方向位移大于垂直位移就判定为横向滑动让ViewPager处理反之让RecyclerView处理。这个“滑动方向判定”的思路比空谈拦截方法更有说服力因为它是真实的处理策略。3.3 Canvas状态管理与硬件加速细节这道题相对偏门但确实有出现。问的是Canvas.save()和Canvas.restore()的作用是什么在硬件加速下要注意什么Canvas的save/restore跟我们理解的事务很像。save会保存当前画布的所有状态包括坐标系、裁剪区域、变换矩阵restore会恢复到最后一次save的状态。这两个方法必须成对出现如果只save不restore代码很隐蔽——后续所有绘制的坐标系偏移会累积导致绘制错位。硬件加速方面2013年之后Android的View绘制默认走了硬件加速Canvas的API大部分都支持但有少数操作比如clipPath和某些drawText的复杂操作在硬件加速下行为不一致。另外硬件加速下Canvas的saveLayer性能开销很大因为它会创建离屏缓冲区如果频繁调用会造成掉帧。这是性能优化的一个重要突破点。我在实际项目里遇到过一个问题自定义折线图在低端机上滑动卡顿查了半天发现是onDraw里频繁创建Paint对象和调用saveLayer。改成在初始化时创建并复用Paint、去掉不必要的离屏绘制之后帧率直接翻倍。这类实战细节在笔试里如果能写出来绝对是大加分项。4. 性能优化与稳定性从“能用”到“好用”卷三后半部分的性能题摆明了是在问你观察过一个App的运行状态吗出题人想要的是有线上问题排查经验的候选人而不是只会写功能逻辑的开发。这部分也是我在带团队时最看重的能力项。4.1 ANR的根因分析与监控方案这道题问得很大线上App产生了ANR你会怎么排查标准的排查思路是用/data/anr/traces.txt文件看主线程的堆栈找到卡死的调用点。但线上环境复杂不是每个用户都能轻松拿到trace文件所以现在主流方案是在自家App里内置一个轻量级的ANR监控模块。我常用的做法是在Application初始化时手动创建一个HandlerThread里面放一个5秒的延迟任务。主线程的Looper空闲时会执行IdleHandler每次执行就刷新这个5秒计时器。如果5秒后计时器没有被刷新说明主线程被阻塞了此时主动抓取主线程堆栈并上报。这个方案不需要root也不需要用户提供文件线上排查效率很高。笔试答这个题时关键是展现出“从线上问题到定位到修复”的完整闭环监控抓取 - 堆栈分析 - 定位到具体代码 - 优化方案 - 验证。只写“看traces文件”是拿不全分的。4.2 内存泄漏的常见姿势与LeakCanary原理内存泄漏题几乎是每次必考。卷三给了一个具体场景一个Activity被销毁了但LeakCanary仍然检测到了泄漏可能是什么原因常见的泄漏原因我列一下也是答题时的排查清单非静态内部类持有外部类引用比如Activity里的Handler、Runnable如果任务还没执行完Activity就被销毁了内部类对象会一直持有Activity引用。单例持有ActivityContext全局单例里存了Activity的ContextActivity销毁了但单例还在。静态变量持有View静态View会持有Activity的Context所以View也不能随便用静态存。资源未关闭BroadcastReceiver没解绑、Cursor没关闭、IO流没关闭、动画还在循环等。然后LeakCanary的原理也要能口述它通过WeakReference监听Activity配合ReferenceQueue。GC后如果WeakReference被加入ReferenceQueue说明对象可以被回收如果迟迟没有被加入说明存在强引用路径LeakCanary会主动触发一次GC再确认最后dump出内存快照通过LeakCanary自带的LeakTrace分析出泄漏链。这道题的答题技巧是从表象到原理再到实践。先说你的判断思路再解释工具工作原理最后落到一个具体的修复案例上。这样面试官会觉得你既理解原理又真的处理过问题。4.3 APK体积优化R8混淆与资源治理卷三关于包体积的题目切入点很落地的一个APK达到80MB有哪些手段能把它的体积压下来先答混淆。从Android Gradle Plugin 8.0开始R8已经成为默认的混淆和压缩工具它不只是删掉无用的代码和重命名类还内置了资源压缩、内联等优化能力。在build.gradle里开启minifyEnabled true和shrinkResources true可以同时裁剪代码和资源。注意R8和ProGuard的区别——R8是ProGuard的替代品既能压缩代码也能做优化使用方式却简单不少。再答资源的治理。最见效的手段是按优先级排列图片转WebP压缩率比PNG高20%-40%既有损也无损模式可选删除无用的资源配合shrinkResources自动移除未引用的对so库做ABI拆分比如只保留arm64-v8a可以直接砍掉一半体积启用App Bundle发布按设备动态分发资源大图改成运行时加载或者用矢量图替代部分小尺寸PNG。这道题最容易丢分的地方是只答混淆不答资源。要知道对于一个内容社区App来说图片资源占的权重远大于代码体积不答资源优化等于答了半个题。4.4 启动优化从冷启动到首帧的拆解启动优化是性能题里的压轴大题。卷三问的是冷启动时App做了哪些事如果你想优化启动速度从哪些方向入手冷启动的流程可以拆成这样系统创建进程加载Application类执行attachBaseContext、onCreate创建主Activity执行onCreate、onStart、onResume首帧绘制完成用户看到界面所以启动耗时的优化空间主要在Application和首屏Activity的初始化里。常见的优化手段包括异步初始化非必需组件放到子线程但要有初始化顺序的管控避免出现子线程和主线程竞争同一资源的竞态。延迟初始化把非首屏必需的初始化放到IdleHandler里等主线程空闲再执行。按需加载ContentProvider的初始化时机比Application还要早这个坑很多人不知道。第三方SDK为了自动初始化会使用ContentProvider每个App启动时都要加载它们数量多了非常影响启动速度。所以选第三方库时优先挑那些支持手动初始化、不搞ContentProvider的。启动器框架Google的Jetpack启动库或者字节的Alpha框架可以构建有依赖关系的异步任务执行图把可以并行的任务并行化串行任务按依赖顺序执行。启动优化在笔试里很难靠死记硬背拿高分关键是能不能按“主线程在启动阶段到底做了什么”这个逻辑线来串联思路。考官想看的不是一个知识点而是一整套分析框架。5. 存储、网络与图片信息流应用的三板斧到了这一块题目开始向小红书的业务场景靠拢了。内容社区App最核心的几条链路图片加载、网络请求、本地缓存。这三块不一定都考但考到基本就是大题。5.1 Glide缓存机制与图片加载优化图像加载是在内容App中极其重要的问题卷三出了一道开放性的看图题——给出一张图片列表的页面问如何保证滑动流畅。这道题实际的考察点是图片缓存的三级架构。Glide默认实现了比较完善的三层缓存活动资源ActiveResources正在被View引用的图片存在一个弱引用的HashMap里内存缓存LruCache最近使用过的图片LRU淘汰磁盘缓存Glide还分了两种——原始数据缓存和转换后的图片缓存默认情况下Glide会缓存转换后比如压缩过、裁剪过的资源。为什么这么设计原因很朴素内存缓存访问速度快但容量有限磁盘缓存容量大但访问慢。如果滑动时每张图都要从磁盘读还是会有IO卡顿。所以磁盘缓存之上还要有一层内存缓存而正在被使用的图要单独存一份防止刚显示就被LRU淘汰出去造成“抖动”。此外图片加载的优化还有几个点缩略图预览、长图采样压缩、WebP格式切换、预加载机制。在RecyclerView滑动场景中可以在onBindViewHolder时对下一屏的图片做preload。这套组合拳打下来滑动流畅度能有肉眼可见的提升。5.2 HTTPDNS与弱网优化网络相关的题考察点比较分散。卷三问过一个比较实际的问题弱网环境下图片加载失败率和速度都不理想怎么优化常见且有效的弱网优化手段有这些超时设置有讲究连接超时和读取超时要区分开不能一个超时时间走到底。弱网环境下过短的连接超时会导致频繁重试过长的读取超时会让用户等太久。重试策略不可以在用户点击后无限自动重试要限制次数和间隔。HTTPDNS绕过运营商DNS的解析从HTTPDNS服务器获取IP避免DNS劫持和调度不准的问题。预连接在列表滑动即将发生网络请求前提前建立连接。数据压缩开启gzip压缩图片用WebP等更高效的格式。很多候选人答这道题只想到“加大缓存、提升服务器性能”这其实是没答到点子上。真正的弱网优化是在客户端侧把每个环节都做到容错、可降级。5.3 数据库升级与ORM选型数据库这题在卷三的权重不大但出现过数据库版本升级时如果新版需要新增表、新增字段你会怎么写升级逻辑最简单的做法是在SQLiteOpenHelper.onUpgrade里按旧版本号做switch分支Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { switch (oldVersion) { case 1: db.execSQL(ALTER TABLE user ADD COLUMN age INTEGER); case 2: db.execSQL(CREATE TABLE new_table (...)); } }注意switch里没有break这是故意的——如果用户从版本1直接升到版本3v1的分支执行完会继续执行v2的分支保证升级路径被完整走一遍。这里有一个特别容易踩的坑不能直接删除旧表重建。用户数据是无价的删表等于丢数据这在线上是要出大事的。如果表结构变更比较复杂可以考虑建新表、迁移数据、删旧表的三步策略。答这道题还有个加分项提一下当前主流ORM。Room在编译期做了SQL验证能暴露SQL语法错误GreenDAO性能好但注解处理繁琐。笔试如果能对比一下选型理由说明你确实在项目里思考过工具选型而不是只会用。6. 架构设计与开放题校招笔试的“最后一公里”最后这部分是最难的因为它没有标准答案。但它也是最容易拉开差距的——为什么因为能答到这里的候选人已经不只是会写代码而是开始有架构意识和业务思维了。6.1 MVC/MVP/MVVM的选择逻辑架构题在卷三出现的概率很高。题目大概是你在项目中使用过MVP还是MVVM优缺点是什么你更推荐哪个不要只回答“MVVM更好”要给出选择逻辑。先看三者的本质区别MVCModel层和View层可以直接交互Controller难以控制代码容易乱成一团。MVPPresenter作为中间人View和Model完全隔离职责清晰但是接口数量爆炸每个页面要写大量contract类。MVVM用ViewModel和LiveData/Flow替代了Presenter的部分职责通过Jetpack生态把数据驱动做得更彻底。ViewModel还能在配置变更时保留状态这是MVP做不到的。笔试如果真的让你选比较稳妥的答法是推荐MVVM理由不是因为它新而是因为Jetpack的ViewModelLiveDataDataBinding这套组合解决了MVP的痛点——View与数据的关系由观察者模式管理状态恢复由ViewModel内部机制处理配合协程做异步任务也很干净。但也要补充一句架构不是越新越好中小项目直接用MVC反而更轻量大项目才需要MVVM这种强约束。能说出这种权衡比无脑推崇MVVM高出一个段位。6.2 组件化与模块解耦组件化是很多中大型Android项目里的常规操作卷三用了一道简答题来问为什么要组件化它解决了什么问题组件化的核心动力是工程效率。当项目有几十个模块、几十人协作时每次编译一次全量工程要花很长时间业务代码之间也容易互相依赖、改一个地方崩一片。组件化把App拆分成独立的模块每个模块可以单独编译、单独交付测试模块之间只通过约定好的接口通信。具体到Android工程里一般会拆成app壳工程负责整体组装基础库组件网络、图片、日志等业务组件首页、搜索、发布、个人中心等模块间的通信方案现在常用的是ARouter这种路由框架通过注解生成路由表用URL或者路径来跳转页面、调用服务。路由的好处是解耦彻底模块之间不需要直接依赖。但组件化有一个坑值得提醒不要为组件化而组件化。中小型项目人数不多强行拆组件反而会降低开发效率。判断标准很简单——编译时间是否已经严重影响开发效率模块间是否已经出现了明显的耦合如果都没有说明还不需要组件化。这道题能答出“什么时候不该做组件化”比单纯吹组件化的好处更容易让考官眼前一亮。6.3 开放题如何设计一个首页信息流这是卷三压轴级别的题目场景感很强如果让你设计小红书首页的信息流页面你会怎么考虑技术和体验方面的设计这类开放题没有标准答案但好的回答会从这五个维度逐一展开数据层面用分页加载还是增量更新下拉刷新和上拉加载如何衔接缓存策略是LRU还是时间过期图片层面信息流以图片为主必须做压缩、采样、预加载保证滑动流畅。内存层面列表页滑动时如何避免图片占用过多内存回收策略是Glide的trimMemory机制还是手动管理长列表的Item复用怎么做体验层面占位图设计、加载失败的重试机制、弱网下的降级方案比如先显示模糊图再加载高清图。性能监控页面FPS、卡顿率、启动耗时、内存占用这些指标如何采集和上报卡顿时如何定位到具体模块我最推荐的答题框架是先定目标用户首屏能快速看到内容、滑动不掉帧、弱网可降级再拆方案数据流、图片流、缓存、监控最后做权衡缓存太多会占存储预加载太多会耗流量。这种从目标到方案的层层推导是面试官最愿意看到的思考方式。如果能在回答里加一两个真实项目中的优化案例——比如“我之前接手一个列表页卡顿是因为每次滑动都触发了一次网络请求后来加了预加载和缓存才解决”——那就完美了。这比任何华丽的术语都更有说服力。7. 复盘与建议踩过的坑希望大家绕开说回这套卷子本身。我接触过的刷这套题的候选人不少总结一下高频丢分点希望大家别在同一个地方摔两次。7.1 最容易丢分的三个地方第一只答结果不答过程。比如问Handler机制直接回答“主线程Looper是死循环但不会卡死”却不解释epoll、不解释消息队列、不解释ANR阈值。这种答案只能拿基础分拿不到高分。第二不会结合实际项目。卷三的题很多都在问“你怎么做”如果只答教科书层面的知识没有个人实践的细节支撑面试官很难相信你真的做过。哪怕是一个很小的优化案例只要真实都能给答案加分。第三开放题写太短。很多人在做完前面的题之后时间不够了开放题只写了几行字。其实开放题的分值往往是最高的写完整比写完美重要。实在没时间也要把能想到的点用“关键词一句话”的方式列出来让考官知道你是有思路的。7.2 给我的刷题建议根据卷三的出题风格给正在准备校招的朋友提几条实际建议刷题不能只刷概念题。每学一个知识点都主动问自己一句这个知识点在我实际的App开发里有什么用如果没用它为什么被面试官反复考动手写项目。没有真实项目的支撑很多题目你就是答不深。哪怕是模仿一个开源项目把网络、图片、列表这几个核心链路跑通都比背100道题更有用。多做复盘。每一道做错的题不要只看一遍答案要弄清楚背后的原理。笔试中同一道题换个角度再考概率很高。我自己带项目的体会是校招笔试其实不是在考你会不会做某道题而是在考你的思维方式——你能不能把一个复杂问题拆解成小步骤能不能从原理推导到实践能不能在开放场景中给出有逻辑的方案。卷三这套题本质上就是把这些能力拆成了一个个可以量化的得分点。把每一道题背后的思考逻辑琢磨透比背熟任何一份答案都重要得多。