ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Android校招笔试高频考点:从四大组件到View与构建工具链

2026/8/30 6:24:17 拓冰建站 浏览量
Android校招笔试高频考点:从四大组件到View与构建工具链 2018年秋天我坐在爱奇艺校招Android工程师第二场的笔试页面里盯着倒计时脑子里反复闪过一个念头为什么同一批岗位要分两场笔试第一场不是已经筛过一轮了吗等我把二十多道题做完、交卷、然后在这几年里陆续帮人改简历、做模拟面试、自己也带过新人之后才真正理解“第二场”这三个字的含义——第一场筛的是“基础没塌的人”第二场筛的是“能干活且愿意往深处钻的人”。那一年Android生态正处在一个微妙的时间点Android 9.0刚发布AndroidX刚进入开发者视野Kotlin已经开始渗透进项目但很多校招候选人还在用Support Library写项目。爱奇艺这场第二场笔试的题目风格并不偏门没有故意刁难人的脑筋急转弯但覆盖面很广Java基础、四大组件、View体系、消息机制、并发线程、数据存储、网络协议全都有所涉及。这篇文章不是给大家还原某道原题的标准答案而是把这场笔试背后真正想考察的东西拆开来讲结合我这些年反复回看这些知识点时的理解给准备Android校招的同学一份可以实操的复习路径。1. 第二场笔试的整卷画像为什么同岗位要分两场考1.1 两场笔试的分工逻辑校招笔试分成两场在大厂里并不少见。第一场往往由招聘平台或集团统一出题覆盖面广题量大目的是“宽进严出”把不熟悉基本语法、连Java集合都搞不清的人先筛掉。第二场则更像用人团队的一次主动考察出题人通常是Android技术负责人或资深工程师题目会贴近他们日常工作中真正遇到的坑——这也是为什么第二场笔试题里四大组件的生命周期、消息机制、自定义View、性能优化这些内容的出现频率远高于第一场。还有一个容易被忽略的点第二场笔试的容错率更低。第一场可以通过刷题海战术碰对不少选择题第二场很多人死在程序阅读题和简答题上因为这类题型没有太多“套路”答得深不深一眼就能看出来。我当时的感觉就是选择和填空大概占一半剩下的一半全是需要写过程、写原因、写调用链路的题目几乎没有蒙的余地。1.2 题型分布与答题节奏以我记忆里那张卷子的结构为参考题型大致可以分为四块。题型大致占比考察重点选择题单选多选30%Java基础、集合、HashMap/ConcurrentHashMap、线程池程序阅读题25%静态代码块执行顺序、继承多态、Handler延时消息简答/分析题30%Activity启动流程、事件分发机制、Binder原理、内存泄漏编程题15%算法题或Android相关的代码补全时间一般是90到120分钟看起来够用但实际做起来非常紧张。程序阅读题往往给一段代码问你输出什么或者问某行代码有没有问题这种题需要对Java字节码层面和Android生命周期都有肌肉记忆。我当时的策略是选择题控制在25分钟内遇到拿不准的多选题先标记不恋战程序阅读题30分钟简答题留40分钟编程题最后用剩余时间硬啃。1.3 一开场就崩掉的人通常崩在哪个环节笔试结束后我跟同场几个同学交流发现最让人痛苦的面试者不是完全不会写而是“会但没写到得分点上”。比如一道Activity启动流程题很多人写得出“startActivity最终会调到AMS”但再往下问“AMS返回之后应用进程这边是谁收到回调主线程消息循环做了什么”就接不住了。这种差一层就够不着的状态恰恰是第二场笔试最想拉开的分差。后来我自己带人复盘时得出一条很实用的经验准备这类笔试不能只看结论要能把一条调用链路从头讲到尾连线程切换的节点都说得清楚。这篇文章接下来的章节就是围绕这个标准来写的。2. 四大组件和进程机制校招卷里最稳定的中档题2.1 Activity启动流程从startActivity到onCreate中间发生了什么这道题几乎可以说是Android校招笔试的“必考题”2018年如此现在也如此。标准答法分两个阶段应用进程发起阶段和系统进程回调阶段。应用进程这半边调用栈大致是Activity.startActivity调用到Instrumentation.execStartActivity。Instrumentation通过ActivityManager.getService()拿到AMS的Binder代理发起跨进程调用。AMS在系统进程里完成Activity栈管理、进程存在性检查、权限校验等逻辑。如果目标Activity所在进程不存在AMS会通过Zygote fork一个新的应用进程并回调ActivityThread.main()。应用进程启动后通过ApplicationThread这个Binder接口向AMS注册。AMS准备好Activity记录后通过ApplicationThread.scheduleLaunchActivity向应用进程发送通知。应用进程收到后把消息封装成LaunchActivityItem通过主线程的HHandler发送到主线程消息队列。ActivityThread.handleLaunchActivity被调用最终走到performLaunchActivity执行Activity的attach、onCreate、onStart、onResume。我在2018年答这题时把1到3写得很细但从第5步开始就含糊了。后来才意识到第5到第7步才是面试官真正想听的“应用进程与系统进程如何通过Binder来回切换”的体现。推荐大家按“进程视角”而不是“方法视角”去记忆这条链路一旦脑子里有了进程边界就不会漏掉ApplicationThread和H这两层。2.2 Service的两种启动方式与生命周期细节Service相关题目在笔试中出现频率没有Activity高但只要出现往往就是送命题与送分题并举。两种启动方式必须区分清楚startService启动后由调用者主动调stopService或service内部调stopSelf才能停止。生命周期为onCreate - onStartCommand - onDestroy。bindService生命周期为onCreate - onBind - onUnbind - onDestroy解绑时如果没有任何绑定关系Service才能销毁。第二场笔试很喜欢考一个点同一个Service先startService再bindService然后只unbindServiceService会不会销毁答案是不会。只要Service还在“已启动”状态就算没人绑定了也不会销毁除非再调stopService或stopSelf。这个题看似简单但当时好多人答错因为大家平时写代码只用了其中一种方式。另一个高频点onStartCommand的返回值。START_STICKY、START_NOT_STICKY、START_REDELIVER_INTENT分别代表什么系统在Service被异常杀死后的重建策略。这部分要理解不能只背单词。START_STICKY的意思是进程被杀死后系统会尝试重建Service但传进来的Intent是nullSTART_REDELIVER_INTENT则会重新传递最近一次的Intent。2.3 ContentProvider与FileProvider被很多人背答案略过的考点ContentProvider在Android四大组件里最容易被轻视因为日常开发中直接写Provider的概率不高但笔试和面试都爱考它的启动时机和跨进程原理。先说启动时机一个App进程启动时ActivityThread.handleBindApplication会先通过installContentProviders实例化所有ContentProvider再回调Application.onCreate。也就是说ContentProvider的onCreate会先于Application.onCreate执行。这个顺序很多人不知道却有项目会踩坑在ContentProvider里使用还未初始化的Application单例就会出问题。FileProvider是ContentProvider的一个重要子类它解决的是Android 7.0以后禁止通过file:// Uri跨应用共享文件的限制。核心配置就两件事在Manifest里声明provider并指定authority和meta-data在xml目录下通过file_paths配置可访问路径然后对外只暴露content:// Uri。例如provider android:nameandroidx.core.content.FileProvider android:authorities${applicationId}.fileprovider android:exportedfalse android:grantUriPermissionstrue meta-data android:nameandroid.support.FILE_PROVIDER_PATHS android:resourcexml/file_paths / /provider当时笔试里有一道跟文件共享相关的场景题看到一堆类似content://com.example.fileprovider/external_root/xxx的路径其实就是让考生指出为什么用content://而不是file://。回答时要落到FileUriExposedException、临时权限授权、Uri私有性这三个维度上。2.4 进程优先级与系统回收策略Android的进程优先级是面试官检验“你清不清楚系统怎么把没用进程干掉”的经典问题。需要分五档背前台进程、可见进程、服务进程、后台进程、空进程。优先级从高到低在内存不足时系统会从空进程开始逐级回收。这里容易丢分的是边界条件。比如“一个进程持有一个前台可见的Activity但它的Service也在运行怎么归类”答案是如果同时满足多个优先级条件按最高优先级算。而绑定过前台ServicestartForeground的进程会被提升到前台进程级别。还有onTrimMemory的几个level——TRIM_MEMORY_RUNNING_MODERATE、TRIM_MEMORY_UI_HIDDEN等笔试中作为程序阅读题出现频率不低建议把级别和含义记清楚。3. 消息机制与View体系拉开差距的“伪基础题”3.1 Handler、Looper、MessageQueue从同步屏障聊到epollHandler是Android异步消息机制的核心也是2018年校招笔试里区分“背书选手”和“真懂选手”的分水岭。我见过很多同学能把Handler的工作流程画得很顺但一问“主线程的Looper为什么不会让主线程卡死”就卡住了。答案在于MessageQueue.next()里没有消息时会让出CPU通过nativePollOnce进入线程睡眠等到有Message入队或者超时时间到了再通过管道/epoll机制唤醒线程。所以主线程不是忙等空转而是真正进入阻塞状态。另一个值得深挖的点是同步屏障。日常开发中post一个普通消息都是同步消息而UI绘制用的Choreographer post的VSYNC回调是异步消息。当Looper发现MessageQueue当前有同步屏障时会跳过所有同步消息优先处理异步消息这样能保证系统渲染任务不被我们post的任务阻塞。这个知识点在那一年已经属于加分项现在几乎成了标配考点。笔试中最常见的形式是给你一段代码在主线程创建了一个Handler然后问延时消息的顺序。如果队列里有多个延时不同的Message你只要能讲清楚MessageQueue是一个按执行时间排序的优先级队列这道题基本就能拿满分。3.2 事件分发机制一次点击从屏幕到页面走了哪几步事件分发是View体系的另一个高频考点。我的建议是把“责任链”模型理解透一个点击事件从Activity.dispatchTouchEvent进入最后落到Activity.onTouchEvent结束中间是ViewGroup.dispatchTouchEvent、onInterceptTouchEvent、子View的dispatchTouchEvent/onTouchEvent这样一层层嵌套。很多人的误区在于认为onInterceptTouchEvent每次都会执行。但注意一旦DOWN事件确定某个子View为接收者后续MOVE和UP事件会直接交给这个目标ViewViewGroup的onInterceptTouchEvent在同一个事件序列中可能不会再被调用除非目标View调用requestDisallowInterceptTouchEvent或ViewGroup自己决定拦截。答题时把“事件流从DOWN开始建立目标MOVE/UP跟随目标”这个思想讲清楚就比死记方法返回值强多了。另外自定义View处理滑动冲突是这类题在编程题里的延伸比如处理垂直RecyclerView里嵌套横向Banner的滑动冲突做法通常是在子View的dispatchTouchEvent里判断是否需要横向消费。当年笔试结束后我才意识到“协调布局Banner”这种看起来像业务需求的问题考察的就是事件分发与嵌套滑动机制的组合知识。3.3 自定义View的测量、布局、绘制MeasureSpec是第一个坎自定义View在笔试题里很少让你现场写完整实现更多是对概念的理解。MeasureSpec是由尺寸和模式组成的一个int值通过位运算打包EXACTLY、AT_MOST、UNSPECIFIED三种模式分别对应什么场景必须张口就来EXACTLY父View已经把确定的尺寸告诉子了比如match_parent或具体dp值。AT_MOST子View最大不能超过某个值典型是wrap_content。UNSPECIFIED没有限制常见于ScrollView和RecyclerView这类可滚动容器。接下来要能说清楚为什么自定义View时如果希望wrap_content起作用必须重写onMeasure并处理AT_MOST模式。因为View默认的measure方法里wrap_content和match_parent都是走EXACTLY模式计算后给一个父View最大尺寸的结果这正是很多自定义View出现“wrap_content和match_parent效果一样”的根因。这个结论许多做了两年Android开发的人都不一定清楚但对校招生来说只要通过源码验证过写进答案里就是明显加分项。3.4 资源与UI细节setColor、透明度和动态图标主题笔试中的选择题很喜欢出一些“死记型”的题看起来简单实际容易踩坑。比如setColor相关getResources().getColor(int id)在Android 8.0以后被标记Deprecated需要改用getColor(int id, Theme theme)或ContextCompat.getColor()。这里考的不仅是API更新更是“有没有关注过新版本兼容性”。透明度对照表也是Android笔试里比较常见的“快速记忆题”。很多同学知道0xFF表示不透明0x00表示全透明但碰到50%透明就蒙了。其实透明度和十六进制对应关系是一组常见值100%不透明FF50%透明8075%透明4020%透明33。笔试中如果碰到“给控件设置80%不透明度的色值”实际上是在考你对十六进制alpha位的理解。动态图标主题在2018年还不是校招重点但后来在系统级开发团队里成了常见需求。Android 8.0以后的自适应图标会根据主题生成不同样式底层是AdaptiveIconDrawable。如果笔试中有涉及资源目录的题目可以顺带提一提launcher主题动态切换的实现思路让面试官看到你的知识边界不停留在Activity。4. 构建与工具链的暗流AGP/R8/APEX背后面试官真正想听什么4.1 R8与ProGuard代码混淆不只是“加几行配置”2018年的Android校招笔试还处在一个有趣的时间节点Google在当年Google I/O上发布了R8作为ProGuard的替代方案但试卷里更多的题目还在问ProGuard的keep规则。R8与ProGuard的核心差异在于R8不仅仅是压缩、混淆和优化它还能做内联、裁剪未使用的代码并且直接把移除Log这类优化做到字节码层面。后来R8在AGP 3.4之后成为默认现在绝大多数Android项目的minifyEnabled走的就是R8。面试题如果深入一点会问你keep规则为什么要写。原因是混淆器无法自动判断反射、JNI、Gson序列化等场景下的类名和方法名如果不加keep在运行期就会因为类名被混淆而崩掉。常见的keep规则包括Model类、WebView JS接口、注解类、自定义View等。笔试能答出“keep的目的是保护动态查找类名的代码不失效”这一层已经超过大多数背模板的人。我还想提醒一句混淆配置里跟release构建相关的资源收缩、shrinkResources以及打包时间变长后的增量编译策略都是面试官比较喜欢引申的点。如果能把“混淆让App更安全只是附属价值真正核心是体积缩减和性能优化”这个认识讲出来就很加分。4.2 Android Studio与AGP2018年的工具链和现在差别在哪里那一年的Android Studio最新稳定版是3.2对应Gradle 4.6和AGP 3.2。现在很多同学一上来就装最新Android Studio比如Hedgehog版本反而对AGP版本与Gradle版本的对应关系不太敏感。其实“AGP版本必须与Gradle版本匹配”这个问题在校招笔试里是个经典陷阱题项目构建失败报错信息是AGP要求的最低Gradle版本不满足问你该怎么解决。如果你能直接说“修改gradle-wrapper.properties里的distributionUrl而不是去升级AS”就说明你真正干过活。另外AGP 8.x之后很多旧的API变了比如buildConfig默认关闭、命名空间必须指定、第三方插件要适配。这些变化在校招中如果作为“场景题”出现本质是在考察你对构建流程的敏感度。我的建议是以自己电脑上装的Android Studio版本为准把对应AGP的构建流程、gradle task生命周期、manifest合并、resource merge这几个核心流程理一遍笔试中遇到工具链方面的问题基本都能接上。有一点要说清楚Android Studio版本的代号如Hedgehog并不重要重要的是它支持的AGP版本范围。面试官问“Android Studio Hedgehog支持AGP 8吗”不是想让你回答支持或不支持而是想引导你说出“AS和AGP是两个独立组件AGP版本决定构建能力AS提供编辑环境”这个本质。4.3 APEX与OTA从一次系统升级问题延伸出的架构视角热搜词里高频出现的android apex、android ota、framework在第二场笔试中更像综合题的材料背景。APEX是Android 10引入的系统模块化包格式用它可以单独升级部分系统组件而不需要刷整个系统镜像。面试官如果问APEX真实意图是看你是否关注过系统组件如何解耦。另一个相关的点是OTA与A/B分区。A/B无缝升级会把新系统写入备用分区用户重启后切换分区升级过程中不中断使用。这在车载、电视等嵌入式Android设备上尤其重要。当时笔试如果只是单纯问“OTA升级流程”你可能觉得这是系统工程师才需要掌握的内容但后来我意识到对应用开发者来说理解A/B分区能帮你排查很多“为什么升级后旧版本数据还在”的问题。如果准备时间充裕建议把Zygote进程启动、SystemServer、PackageManagerService这几个框架核心类看一遍。2018年这场笔试没有直接考哪个类但它让我们那批人意识到Android面试的上限其实是系统源码理解能力而不是背API。4.4 从“会用AS”到“会分析性能”火焰图这类工具链知识android studio火焰图在热搜词里是一个很经典的性能分析场景。笔试题目偶尔会给你一个CPU Profiler记录让你判断卡顿出现在哪个方法。答案通常是通过火焰图找宽且长的函数栈而不是看哪个函数调用次数最多。宽说明该层级有很多方法调用长说明单次时间很长两者结合才能定位热点。这类题在2018年第二场笔试里出现的比例不高但属于“如果你会就已经赢了一道题”的知识点。建议提前在模拟器里跑一次CPU Profiler学会用Recorded Method Tracing和System Trace区分“CPU密集型耗时”和“等待型耗时”这样不管笔试还是面试遇到性能分析题都有真实经验。5. 笔试之后才想明白的事复盘2018真题与现在校招的对照5.1 当年考试中我犯过的三个典型失误第一个失误是JVM类加载顺序题。程序阅读题里给了父子类的静态块、成员变量初始化、构造函数顺序我一开始就被“父类初始化一定先于子类”这种笼统结论带偏了。实际上完整的顺序是父类静态变量/静态块 - 子类静态变量/静态块 - 父类成员变量/构造块/构造函数 - 子类成员变量/构造块/构造函数。如果类之间存在继承关系这个顺序在笔试中几乎是必考的。答错的原因不是不会而是没把“类加载阶段”和“实例创建阶段”分开想。第二个失误是Handler的延时消息题。题目问两个延时50ms的消息先后post为什么后面post的消息可能先执行。我第一反应是“队列按时间排序”但这个答案不够准确。关键点是如果两个消息时间相近队首消息被取出时还没到执行时间Looper会进入阻塞但如果中间有同步屏障或异步消息插队时间顺序就会被打乱。这类题考的不是排序算法而是“同步屏障可以跳过同步消息”这个机制。第三个失误是简答题踩了“背大段源码”的坑。我以为把Activity启动流程中的所有方法名都写上就能得分但批改者关心的其实是“应用进程和系统进程之间的通信协作逻辑”。后来我才明白简答题写方法与写逻辑分数差别很大。把一条链路的“角色”讲清楚远比罗列方法名更有价值。5.2 从“会背概念”到“能串联原理”校招考察方向的迁移2018年的Android校招笔试整体风格是“考基础、考细节、考机制”。等到这几年我再看各家的校招题明显感觉到三个变化一是Kotlin协程与Flow出现频率逐年上升二是性能优化从加分项变成常考项三是越来越多的题目要求学生把框架源码、Binder、Hooks、插件化这些“高级话题”串成一个完整知识体系。这个迁移背后有个很现实的原因Android开发者的基础技能已经很难通过一两个API考察出水平面试官更想看到候选人是否具备“遇到bug能顺藤摸瓜到系统层”的能力。所以现在的复习方式不应该是一题一题刷而是把一个主题挖到足够深然后往相邻主题扩散。5.3 给现在准备Android校招的读者几套自学自查题启动流程深挖Launcher点击图标从桌面到MainActivity显示中间经历了几次跨进程调用Application、ContentProvider、Activity.onCreate的执行顺序是什么Handler深入主线程为什么默认有Looper子线程为什么必须调用Looper.prepareMessageQueue中有同步屏障时普通延时消息的执行会受什么影响View体系MeasureSpec三种模式分别对应什么布局场景在ScrollView嵌套RecyclerView时为什么会出现测量异常自定义View的onMeasure里该怎么处理AT_MOST内存优化LeakCanary的检测原理是什么它是通过什么方式知道对象已被弱引用无法回收的模拟一次内存泄漏说明怎么在Android Studio里用Memory Profiler定位。网络与数据OkHttp的拦截器链如何设计Retrofit的动态代理如何把接口方法转成HTTP请求这两个框架的组合几乎成了校招框架题的标配。跨进程通信AIDL的Stub代理结构、Binder驱动的一次拷贝原理、oneway对调用线程的影响。文件存储SharedPreferences为什么不适合存大对象DataStore和MMKV各自解决什么问题FileProvider的content:// Uri怎么授权给其他应用访问。5.4 笔试结束后我建议你做一张错题索引表最后再分享一个具体操作考完笔试后趁记忆还热把每道题的考察点、当时的思路、正确答案、错因整理成一个表格。不需要漂亮但要能区分开“知识性错误”和“思维性错误”。就这场2018年第二场笔试来说我给自己建的索引表里知识性错误大概占40%比如透明度换算记错、进程优先级边界没分清思维性错误占60%比如流程链路答了一半卡住、知道框架但说不出设计意图。现在回头看这两类错误对应的是两种不同的复习动作知识性错误需要反复记忆和题目巩固思维性错误需要逼自己把每条链路从头到尾讲一遍。第二场笔试独特的价值恰恰是让你在走向面试前暴露这些问题——它不是为了淘汰你而是为了提醒你还有哪些可弥补的缝隙。