前阵子整理旧硬盘,翻出一份当年京东2019春招Android开发类岗位的笔试记录。说实话,看到文件名的瞬间,很多画面就回来了——那时候我还在为第一份大厂Offer刷题,凌晨两点对着Activity启动模式画思维导图,第二天爬起来继续啃算法。现在再回头看,那套卷子的题型和考点,基本就是整个电商Android招聘市场的风向标:算法考得刁、机制问得深、性能优化处处围着业务转。这篇文章就用来复盘那套卷子背后的备考逻辑,把每一类题型拆开揉碎,讲清楚它到底在考什么、该怎么准备。
如果你的目标也是电商类大厂的Android开发岗,或者你正在准备春招、秋招,这套思路可以直接拿来用。我不打算复述原题,而是把当时考完之后复盘出来的完整备考链路写给你,让大家少走点弯路。
1. 先搞清楚京东笔试在考什么:电商场景下的Android必备能力
复习之前,我建议大家先做一个动作:站在招聘方的角度想一个问题——京东这种体量的电商App,Android开发团队每天在解决什么问题?
打开京东App,首页信息流、商品详情、购物车、订单列表、搜索页,每一个页面都是数据密集、交互复杂、用户量千万级的场景。大促期间流量峰值能把服务器压到喘不过气,手机端要保证页面不卡、不乱、不崩。多团队并行开发,几个百人的Android团队同时在一个代码库上协作,代码冲突、模块耦合、编译时间都是问题。
有了这个背景,你再去看笔试题目,就会觉得它出得有逻辑了。京东这类的笔试,绝对不是为了考倒你,而是在筛选“能直接上手干活的工程师”。算法题考的是编程基本功和代码洁癖;Java/Kotlin基础考的是语言功底;Android机制考的是你对系统的理解深度;性能优化和架构题考的是你处理真实业务问题的能力。
1.1 为什么考这些不考那些:业务特点决定考点
2019年那会儿,移动端技术栈正处于一个很微妙的节点。Kotlin已经被官方扶正,Flutter刚发布1.0没多久,AndroidX迁移正在轰轰烈烈地进行。但电商App的Android代码存量非常大,线上跑着的核心链路依然是Java + 传统View体系。所以笔试的考察范围很务实,基本可以归纳成几个关键维度:
第一,并发与多线程。电商App有大量异步任务:图片加载、网络请求、数据库读写、任务调度。你不可能在主线程里做耗时操作,那就要对线程池、锁、Handler、AsyncTask(虽然已经被弃用了,但当年的题还是会带一嘴)有清晰认知。第二,流畅度与稳定性。列表滑动卡顿、启动黑屏、内存暴涨、ANR频发,这些是电商App的常见痛点,针对这些场景的题目几乎是必出。第三,架构与工程化。大团队协作下的模块化拆分、代码复用、组件通信,笔试里会通过开放题来考察你的架构意识。
所以你看,京东笔试并不是要筛“刷题机器”,而是要筛一个“对移动端有整体认知、能解决真实问题”的人。备考的时候,如果只埋头刷题不思考业务场景,那拿到问答题很容易懵掉。
1.2 试卷的常规模块分布与备考优先级
一般来说,这样一场开发岗笔试的卷面结构会分为几块:选择题、填空题、编程题和问答题。选择题和填空题通常是语言基础和Android基础概念,覆盖面广但深度不算深;编程题一般是2道左右,难度从中等到偏难;问答题则是2到3道,围绕性能、架构、或者某个具体机制让你写出分析思路。
备考优先级上,我个人的建议是:算法 > Android核心机制 > Java基础 > 性能优化 > 架构与新技术。算法必须最先搞定,因为它是硬门槛,代码题没AC的话后面再优秀也很难进面试。Android核心机制是专业分的大头,四大组件、Handler、Binder、事件分发这些都是必问的。Java基础是很多人的盲区,因为平时写业务不太用到,但笔试选择填空很喜欢出。性能优化和架构题分值占比高但不好押题,需要靠平时的知识积累和项目经验去答。
2. 算法题:电商笔试里的“送分题”和“拉分题”
算法题是整套卷子里区分度最大的一块。为什么这么说?因为选择题你可以蒙,问答题你可以编,但代码题是实打实跑测试用例的。通过率就是通过率,没有侥幸的可能。我当时备考的时候把LeetCode hot 100刷了三遍,笔试实际遇到的题目其实不算超纲,但题型分布很有规律。
2.1 高频题型:链表、二叉树、动态规划
电商场景下,算法题的高频考点其实和业务有隐秘的关联。链表的题会出现反转链表、合并有序链表、判断环形链表;二叉树会出现层序遍历、最近公共祖先、路径总和;动态规划会出现爬楼梯、最长公共子序列、01背包。字符串的题也不能忽视,括号匹配、最长回文子串都考过。
为什么这些题高频?因为它们的解题思路可以迁移到真实业务中。链表反转对应着数据结构的灵活操作,二叉树层序遍历对应着层级数据的处理逻辑,动态规划对应的则是复杂问题拆解成子问题的能力。面试官不会直接问你“商品分类树怎么遍历”,但你看过二叉树层序,再去看商品分类的多级列表,思路是相通的。
备考的时候不要光刷题不总结,建议按类型整理模板。比如树相关的题,递归、BFS、DFS三种套路吃透,剩下就是改参数。链表相关的题,画图比空想重要一万倍,复杂指针操作画个图很快就理清了。
2.2 一道典型的算法题及完整解题思路
写一道我当时印象很深的真题变体:给定一棵二叉树,返回它的锯齿形层序遍历,也就是先从左往右,再从右往左,下一层再从左往右,以此类推。这道题考的是BFS(广度优先搜索)和双端队列的配合,难度不高,但非常典型。
解题思路是这样的:外层用队列做层序遍历,每一层单独处理。关键点在于如何实现“锯齿”效果。最简单的做法是维护一个boolean变量表示从左还是从右,然后每一层结束的时候翻转一下。具体实现时,每一层的节点值放进一个LinkedList,从左往右遍历就addLast,从右往左遍历就addFirst,这样避免了每层结束后再reverse的开销。
边界条件要特别小心:二叉树为空时直接返回空列表;只有根节点时也要能正常走通。复杂度方面,每个节点只访问一次,所以时间复杂度是O(n),空间复杂度是O(n)。
我当时做这类题踩过一个坑:写BFS时忘了在循环开始时先记录当前队列的size,然后在循环体内把整个队列全部poll出去,导致多套了一层循环,逻辑全乱了。后来养成一个肌肉记忆:凡是层序遍历,先int size = queue.size(),再进入for循环处理这一层。这个细节,笔试时会让你的代码干净很多。
2.3 做题节奏与代码规范细节
编程题的做题节奏直接影响你整场考试的心态。我的策略是:先把有思路的题写完再优化,千万不要卡在一道题上死磕。遇到一道题读了两遍还没思路,先跳过,做后面的,全部做完再回头攻难题。有时候做完后面的题,脑子反而松动了,回头看难的题会有新思路。
还有一个容易被忽略的点:代码规范。笔试系统虽然会跑测试用例,但人眼阅卷(尤其是问答题旁边的代码题)也会看你的代码风格。变量命名要有意义,不要用a、b、c;该判空的地方要判空;函数不要太长。我当时写完代码还会顺手加一两个关键注释,既方便阅卷人理解,也显得自己思路清晰。
3. 语言与Android核心机制:那些改卷老师一眼就能看出水平的题
算法题过了,再往下就是选择题填空题的主战场:Java/Kotlin语言基础和Android核心机制。这一块非常考验积累的深度,背八股文能拿基础分,但想拿高分必须有真正的理解。
3.1 Java/Kotlin语言基础考点
Java的基础考点无外乎这几块:HashMap底层实现(JDK 7和JDK 8的区别)、synchronized和volatile的区别、ReentrantLock和synchronized的对比、线程池的关键参数和执行流程、JVM运行时内存区域划分、垃圾回收算法和常见收集器。这些内容在2019年是大厂笔试标配,到今天依然是Android面试的高频点。
为什么考这些?还是回到业务场景。电商App的搜索、排序、缓存,底层全是集合和算法;网络请求并发量高,必然要对线程池有清晰认知;性能优化做到后面,内存问题绕不开JVM和GC。所以这些题不是纯粹考背诵,而是在考察你写代码时有没有底层意识。比如你知道HashMap在Java 8改用红黑树解决哈希冲突,那你在写高并发缓存的时候就会主动考虑ConcurrentHashMap而不是HashMap,这就是面试官想看到的。
Kotlin的话,2019年已经是一个绕不开的话题了。考卷里可能会涉及空安全、扩展函数、协程。协程是重点,它解决了回调地狱的问题,让异步代码写起来像同步代码,底层是状态机实现。笔试通常会问协程和线程的区别,回答的关键点在于:协程是用户态的轻量级调度,不依赖操作系统线程切换,所以可以开几十万个而不会栈溢出。
3.2 Android四大组件与Handler机制
Android核心机制是整张卷子专业分的重头戏。四大组件中,Activity是考察最多的,启动模式(standard、singleTop、singleTask、singleInstance)几乎是必考题。不要只背概念,要理解每个模式的应用场景。比如singleTop适合接收通知跳转的页面,避免多次点击重复创建;singleTask适合App的主页和WebView容器页,保证整个栈里只有一个实例;singleInstance适合电话、闹钟这类需要全局唯一的页面。
Handler机制更是重灾区。面试官喜欢让你从Handler、Looper、MessageQueue、ThreadLocal四个角色讲清楚消息循环的完整流程:主线程通过Looper.loop()进入消息循环,MessageQueue按时间顺序排列消息,Handler通过sendMessage把消息塞进队列,Looper再按顺序取出消息交给handleMessage处理。ThreadLocal保证每个线程只有自己的Looper,这设计很精妙。笔试时如果能把“为什么不能在子线程更新UI”从Handler机制的角度说明白,就比只答“因为系统不允许”高出一大截。
事件分发机制也是热点。dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三个方法的关系,以及事件从Activity到ViewGroup再到View的传递顺序,这个必须画图记牢。真实的业务场景——比如RecyclerView嵌套滑动冲突怎么处理——就是考察这些基础机制的运用。
3.3 这些题怎么体现真实经验
这一块我吃了不少亏。第一年备考时,我把启动模式背得滚瓜烂熟,但笔试遇到“一个App有两个Activity,A启动B再启动C,此时按Home键再点击桌面图标,发生了什么”这种场景题时,还是有点发懵。因为业务里很少遇到栈内全部Activity重建这种极端情况,所以做题时没思路。
后来我换了一种复习方式:每个机制都搭配一个真实的踩坑案例去理解。比如Handler内存泄漏,就找一段自己项目里写过的错误代码:“new Handler() { handleMessage... }”在Activity里的使用,然后理解为什么静态内部类加弱引用可以解决泄漏。有了场景感,再遇到问答题就不会无话可说。
这里建议备考的朋友做一个动作:把每个核心机制整理成“是什么+为什么+怎么用+踩过的坑”的四段式笔记,比泛泛地翻书管用得多。
4. 性能优化与稳定性:电商App最在意的两件事
京东的Android工程师日常工作中,性能优化和稳定性监控一定是占比很大的部分。试卷里的问答题也经常会往这个方向出。我当时遇到的题目大致是:App启动速度慢,你怎么定位和优化;线上Crash率偏高,你如何搭建监控体系;RecyclerView滑动卡顿,你的排查思路是什么。这些题完全不考背诵,全看你有没有真实处理过。
4.1 启动优化、布局优化、内存优化
启动优化是每年必考的老题。冷启动的过程可以拆解为:进程创建、Application初始化、首帧渲染。优化的核心思路就一句话:减少主线程的耗时工作。Application里不要做耗时初始化,能异步的全部异步;SharedPreferences的读取也是耗时的,能延迟就延迟;一些第三方SDK的初始化可以通过启动器框架做任务调度,让不依赖主线程的初始化任务并行执行。
布局优化考得也比较具体。最直接的思路是减少View层级:能用LinearLayout就别嵌套多层RelativeLayout,能合并的布局用merge标签,需要时再加载的用ViewStub。2019年的时候ConstraintLayout已经是官方推荐了,它能用一套约束关系解决大部分复杂布局,层级大幅减少。真题可能会给你一个XML布局让你分析哪里冗余,这种题靠的是平时多写多看的经验。
内存优化的核心是避免泄漏和减少压力。常见泄漏场景是:单例持有Activity、静态变量引用View、Handler的匿名内部类、没有注销的注册监听器。Bitmap是内存大户,一张1920x1080的ARGB_8888图片就是差不多8MB内存,优化思路包括按需采样、使用LruCache做缓存、用复用的方式加载图片。
4.2 卡顿、ANR、Crash的排查思路
卡顿问题的排查是加分项。主线程在做耗时操作会导致丢帧,正常60fps是每帧16.6ms,超过这个时间用户就会感觉到卡。定位手段一般是:先复现,再用Systrace抓trace,看主线程在忙什么;或者接入BlockCanary做线上监控,把主线程的耗时方法直接堆栈打印出来。笔试的时候你不需要写出具体工具怎么用,但要把思路说明白:卡顿是谁引起的、是CPU耗时还是IO等待、是布局太复杂还是主线程有计算量,然后针对不同原因给出对应的方案。
ANR也是一个高频考点。ANR有几种类型:输入事件5秒没处理完、BroadcastReceiver 10秒没执行完、Service 20秒没执行完。笔试常问的是“App发生ANR,你怎么排查”。回答思路是:拿到/data/anr/traces.txt文件,找到对应的线程,看它阻塞在哪里。常见的阻塞原因是主线程在做IO操作、或者死锁、或者等待某个锁。查完之后对应修复:耗时操作全部挪到子线程、用线程池而不是直接new Thread、避免在主线程加锁。
Crash的排查主要分Java层和Native层。Java层的崩溃通过Logcat的堆栈信息定位到具体行号,一般比较容易修。Native层的崩溃要复杂很多,需要借助logcat里的DEBUG输出和tombstone文件来分析,2019年时美团和微信已经开源了各自的Native监控方案,原理大同小异,都是通过捕获信号量来拿到崩溃时的线程栈。
5. 架构与新技术:开放题怎么答才不被扣分
整个Excel的最后一部分,往往是几道开放题,问的是你对于架构设计和技术选型的看法。这种题没有标准答案,但阅卷人一眼就能判断你是“有思考的工程师”还是“只会写业务代码的码农”。
5.1 组件化、插件化、热修复
组件化的题目很常见,因为它直接对应大公司的协作痛点。当几百人同时在一个App上开发时,如果不做模块拆分,编译速度慢到让人崩溃,代码冲突也每天都会发生。组件化解决的就是这两个问题:按业务拆分成独立的Module,每个Module可以单独编译;模块之间通过路由通信,比如ARouter这样的方案。回答这种题的时候,如果能说出“代码隔离、独立编译、按需初始化”这三个关键词,就有了骨架;如果还能补充模块间通信的几种方式(接口下沉、路由转发、事件总线),那就是高分回答。
插件化和热修复是大厂比较喜欢的加分题。插件化的核心是动态加载技术:通过DexClassLoader加载外部的dex或APK,再通过Hook系统组件的方式把插件的Activity等组件注册进来。热修复的原理是在Java层或Native层做方法的替换。2019年的时候,微信的Tinker方案用的就是Native层替换,它的核心是先加载补丁包中的新类,再通过Native修改ArtMethod的入口地址,让原本的Bug方法不再被调用。
这些技术在电商团队里不是天天用,但笔试考它是有原因的:它考察你对Android底层机制(ClassLoader、Binder、Art虚拟机)的理解深度。如果你平时只是用现成的框架,而不去读源码,真遇到这种题很难答好。
5.2 2019年前后的技术风口:Kotlin、Flutter、AndroidX
大厂笔试还有一个特点:喜欢考察你对最新技术动态的敏感度。2019年的几个风口,一个是Kotlin成为Android官方支持的语言,一个是Flutter发布1.0正式版,另一个是AndroidX全面替代support库。笔试题里可能会出现“你怎么看待Flutter和React Native的对比”这种开放题。
回答这种题,不需要站队,需要的是全面的技术评估能力。Flutter使用自绘引擎,对UI的渲染性能控制力更强,跨平台一致性好;React Native依赖JavaScript桥,动态性更好;Weex在阿里系有特定生态。如果你能进一步说出Flutter的Dart语言的编译机制(JIT用于开发、AOT用于发布),那就已经超出普通候选人的水平了。
AndroidX的问题相对简单,但要注意理解它背后的设计思路:它把support库中的组件独立出来,统一了版本,降低了兼容性痛苦。笔试偶尔会问“为什么要迁移到AndroidX”,回答要点是:原support库的包名混乱、版本分散,AndroidX通过新的包名和独立版本来解决这些问题。
6. 从笔试到Offer:我的做题节奏和复盘方法
写到这里,基本把笔试的知识点覆盖了一遍。但最后想聊聊比刷题更重要的事情:做题节奏和考后复盘。
6.1 笔试现场的时间分配
一套卷子一般90到120分钟。我的建议是:选择和填空题控制在25到30分钟之间,不会的题先靠第一直觉选一个,不要恋战。编程题留够60分钟,至少保证一题AC,另一题有思路。问答题放在最后,优先答有把握的,每题写满三到四个要点。注意不要空着,开放题就算不会也要把自己对问题的理解写出来,阅卷人看到你愿意思考,也会给过程分。
6.2 复盘清单和知识点补强顺序
考完之后,第一时间要做复盘。我当时把错题分成了四类:算法不会做、概念记混淆、机制理解不到位、开放性题目没思路。每一类单独记在一个本子上,后面针对性地补强。算法不会做,就找同类型题刷五道;概念记混淆,就把易混淆的概念做一张对比表;机制理解不到位,就去找对应的源码或者技术博客精读一遍;开放题没思路,就逼着自己针对一个技术点写一篇上百字的学习笔记。
很多人在笔试挂掉之后只知道自己没考好,但具体哪里没考好说不清楚。这样下一场笔试大概率还是同样的结局。复盘不是走形式,而是要把自己的知识漏洞血淋淋地挖出来。
备考期间的最后一到两周,我做的不是大量刷新题,而是回头翻自己的错题本和笔记,把以前不懂的点一个个扫干净。那种感觉就像是在把漏水的船一点点补好,虽然补丁难看,但至少不会再沉了。
根据我个人踩过的坑来看,春招笔试最怕的不是知识点难,而是复习没有重点、做题没有节奏、考后没有复盘。如果你能静下心来把这篇文章里提到的几个模块逐一攻破,相信你拿到的不只是一场笔试的通过通知,而是对整个Android开发体系更深一层的理解。这套方法后来也帮我拿下了好几家大厂的面试机会,希望它同样能帮到你。