尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

小红书Android校招笔试题深度解析:大厂考点与备战指南

小红书Android校招笔试题深度解析:大厂考点与备战指南 1. 小红书2020校招Android方向笔试题解析从一套题看大厂筛选逻辑先直接说结论小红书这套Android校招笔试题在2020年那个时间节点放到今天来看依然很能打。它没有故意刁难人也没有堆砌偏难怪题而是非常克制地在考察一个应届生“到底有没有真正写明白过Android”。整张卷子覆盖了Java基础、Android四大组件、Handler消息机制、自定义View、性能优化、网络与数据存储等多个维度难度阶梯做得比较分明前面是送分题中间是拉分题后面是区分度很高的综合题。我当时刷这套题的时候有一个很强烈的感受它不像是在考“你背了多少面试题”而是在考“你平时写代码的时候有没有想过为什么”。比如同样问Handler它不会只问你Handler的用法而是会结合Looper、MessageQueue、ThreadLocal去追问整个消息循环的运转逻辑。同样问自定义View它也不是让你背onMeasure/onLayout/onDraw的调用顺序而是会给你一个实际场景让你去分析测量规格和布局逻辑。这篇文章我会把整套题按考察方向拆开来讲每一类都给出核心考点、解题思路、以及我在实际开发和面试复盘中的一些体会。无论你是准备校招、实习转正还是工作两三年后想回头补基础这套题都值得认真过一遍。1.1 小红书笔试的核心特征基础扎实比炫技重要先聊聊这套题整体给我的感觉。小红书作为内容社区类产品技术栈在2020年已经相当成熟客户端团队对Android基础的要求是实打实的。从笔试题目来看它明显偏好那些“用得最多、但最容易讲不透”的知识点比如Handler、RecyclerView缓存机制、Activity启动模式、内存泄漏场景等。这套题还有一个特点很多题目表面在问一个点实际上在问一个面。举个例子一道关于Activity启动模式的题表面上问你singletask和singleinstance的区别但如果你真的想把这道题答完整你至少需要串联起任务栈、onNewIntent回调、Intent flag的覆盖规则、以及不同启动模式在具体业务场景中的选型理由。这就是典型的“以点带面”考法。另外小红书这套题对Kotlin的考察占比已经有所体现这在2020年是比较前瞻的。当时很多公司的笔试题还在全量使用Java但小红书已经意识到Kotlin在Android开发中的趋势。这对现在备考的同学也是一个信号语言层面的积累不能停在“能看懂”的层面而是要能够用Kotlin独立完成设计和实现。1.2 从题型分布看考察意图整套卷子的题型大致可以分为四块客观选择题、概念简答题、代码阅读题、综合设计题。这四类题型的考察意图其实各不相同。客观选择题主要筛掉基础不牢的候选人覆盖范围包括Java语法细节、集合类特性、并发编程、Android生命周期、布局渲染原理等。这部分题目单个看都不难但如果基础不扎实很容易在一两个模糊选项上翻车而且选择题往往是多选错选漏选都不得分。概念简答题则是看你能不能把“用过的东西”讲清楚。比如让你简述Handler机制的原理、说明MVP和MVVM的区别、解释一下ANR产生的原因和排查思路。这类题目没有标准答案但答得好不好面试官一眼就能看出来。机械背诵八股文和真正理解原理的人在文字表述上的颗粒度是完全不同的。代码阅读题和综合设计题是整张卷子的分水岭。前者会给你一段常见但有坑的代码让你找出问题并说明原因比如发生在子线程更新UI、静态变量持有Activity引用、自定义View中直接new对象造成GC频繁等问题后者则是开放性的比如让你设计一个图片加载框架的缓存策略或者设计一个IM消息列表的架构方案。这类题目最能体现候选人的工程思维和设计能力也是我们今天要重点拆解的部分。2. Android技术核心考点逐项拆解从Java基础到Handler机制2.1 Java基础与并发大厂笔试万年不变的基石小红书这套题在Java层面的考察主要集中在集合类、equals/hashCode、并发编程三个方向。先说集合类HashMap几乎是必考的尤其是它从JDK 1.7到1.8的变化——底层数据结构从数组加链表变成了数组加链表加红黑树以及扩容机制、负载因子、put流程中的hash扰动。我建议准备笔试的同学一定要能手写HashMap的put流程并且能说清楚为什么树化的阈值是8。再来看equals和hashCode这个考点看起来简单但很多人理解得很浅。笔试常考的形式是重写equals的时候为什么必须重写hashCode如果你用HashMap存储自定义对象不重写这两个方法会出现什么现象答案的关键在于HashMap的查找流程是先比较hash值定位桶再通过equals确定对象是否相等。如果两个对象equals相等但hashCode不等它们会被散列到不同的桶中导致HashMap无法正常查找。这个点在实际开发中踩坑的概率极高。并发编程方面synchronized和volatile的区别是必考题ReentrantLock和synchronized的对比也经常出现包括公平锁、可中断、多个条件队列等特性。除此之外CAS和Atomic类、线程池的核心参数corePoolSize、maximumPoolSize、workQueue、handler策略也是高频考点。这里我给一个备考建议不要死记概念一定要写代码验证。把线程池的四种拒绝策略分别写个小Demo跑一遍让线程池溢出、拒绝、丢弃最老任务你才能真正理解它们的使用场景。2.2 Android四大组件启动模式与生命周期是重中之重四大组件里Activity是绝对的考察核心。启动模式这块standard、singletop、singletask、singleinstance四个模式的差异和应用场景必须滚瓜烂熟。其中有一个比较容易混淆的点singletask模式启动时如果任务栈中已经有了该Activity实例系统会把它上面的Activity全部出栈并回调onNewIntent而不是重新创建实例。我在实际项目中用singletask做过App主界面底栏Tab的防重复创建这是比较典型的应用。Activity的生命周期也是逢考必出。常规的onCreate到onDestroy流程大家都能背但有两个场景很容易翻车一是屏幕旋转时的生命周期变化Android 9及以下默认会销毁重建Activity执行顺序是onPause、onSaveInstanceState、onStop、onDestroy、onCreate、onStart、onRestoreInstanceState、onResume二是从Activity A跳转B再返回时A和B的生命周期切换顺序是A.onPause、B.onCreate、B.onStart、B.onResume、A.onStop返回时则是B.onPause、A.onRestart、A.onStart、A.onResume、B.onStop、B.onDestroy。这个顺序在面试中高频出现建议自己动手打日志验证一遍比背十遍都管用。Service和BroadcastReceiver在2020年的笔试中权重不算特别高但也会涉及。Service要掌握startService和bindService两种启动方式的区别以及对应的生命周期差异还要理解前台Service的作用和8.0之后的限制。BroadcastReceiver要关注静态注册和动态注册的区别以及Android 8.0对隐式广播的限制。ContentProvider虽然是四大组件之一但在笔试中出现频率相对较低。不过小红书这套题里至少有一道与ContentProvider相关的题主要考察getType方法的作用、ContentResolver的增删改查、以及ContentObserver的监听机制。如果你简历上写了“使用ContentProvider实现跨进程数据共享”这类项目经历建议把query、insert、update、delete四个方法和Binder跨进程调用的关系搞清楚。2.3 Handler消息机制不只是八股文更是理解主线程运行的钥匙Handler这套机制在Android笔试中的地位怎么强调都不过分。它不只是面试八股而是理解整个Android运行时的关键钥匙。很多同学能背出“Handler通过sendMessage把消息发送到MessageQueueLooper通过loop方法不断从MessageQueue中取出消息最终回调handleMessage”但一旦被追问细节就答不上来。我建议从以下几个层次去掌握Handler机制第一层主线程Looper的创建时机。ActivityThread的main方法中会调用Looper.prepareMainLooper()创建主线程Looper然后调用Looper.loop()进入消息循环。这就是为什么我们在主线程中可以直接new Handler的原因。第二层ThreadLocal的作用。每个线程都有自己的LooperThreadLocal保证了一个Looper只能属于一个线程。主线程Looper和子线程Looper彼此隔离互不干扰也是通过ThreadLocal实现的。第三层MessageQueue的阻塞和唤醒机制。MessageQueue的核心是enqueueMessage和next两个方法next在没有消息时会通过nativePollOnce进入阻塞状态释放CPU当新消息入队时通过nativeWake唤醒。这个机制涉及Linux的epoll和eventfd但笔试阶段只需要理解“阻塞-唤醒”的设计意图即可。第四层同步屏障和异步消息。这个知识点在2020年已经可以拉开差距了。ViewRootImpl在UI绘制时会通过postSyncBarrier插入同步屏障优先处理异步消息从而保证UI绘制的及时性。如果你能把这层讲清楚面试官基本会认定你对Handler机制有深入理解。如果笔试或面试中遇到Handler相关的代码题最常见的坑就是在子线程中new Handler然后直接调用sendMessage。子线程默认没有Looper必须调用Looper.prepare()和Looper.loop()才能正常工作。另外还有内存泄漏的问题Handler持有Activity的隐式引用如果在onDestroy时没有移除消息MessageQueue中持有Handler引用就会导致Activity无法被GC回收。推荐的写法有两种一是使用静态内部类加WeakReference二是在onDestroy中调用handler.removeCallbacksAndMessages(null)。2.4 自定义View与事件分发从测量到绘制的全链路理解自定义View在Android笔试中属于“看起来难、实际上有套路的”题目。小红书这套题不会让你直接手写一个复杂控件而是更倾向于考察你对View工作原理的理解以及对常见问题的排查能力。View的工作原理要从三个方法说起。measure阶段确定View的宽高layout阶段确定View在父容器中的位置draw阶段完成绘制。这三个阶段对应onMeasure、onLayout、onDraw三个回调。笔试常考的onMeasure中MeasureSpec的三种模式UNSPECIFIED、EXACTLY、AT_MOST。用生活化的比喻来解释EXACTLY像是给你一个固定尺寸的箱子你必须填满它AT_MOST像是给你一个最大尺寸限制你可以比它小但不能超过UNSPECIFIED则是完全没有限制你想多大就多大。自定义View的笔试题目通常有两种出法。第一种是让你手写自定义View的关键代码比如圆形进度条、评分控件、流式标签布局这类常见控件。这种题考察的是你是否真的写过自定义View对onMeasure中wrap_content的处理、onDraw中Paint和Canvas的使用、属性动画驱动刷新的流程是否熟练。第二种出法是给你一段现成的自定义View代码让你找出性能问题比如直接在onDraw中创建Paint对象、没有调用setLayerType开启硬件加速、在onMeasure中做复杂计算等。事件分发机制也是自定义View方向的核心考点。dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent三者的调用顺序和返回值含义要烂熟于心。这里最容易混淆的是Touch事件的传递方向是从父到子自上而下但处理方向是从子到父自下而上。如果子View没有消费事件事件会层层向上回传到父View的onTouchEvent。还有一个高频考点是ACTION_CANCEL什么时候触发比如父View拦截了事件、或者子View在滑动中被父View抢走了控制权。如果你在简历中写了自定义View相关的项目一定要把“为什么选择自定义View而不是组合View”“如何解决滑动冲突”“如何做性能优化”这三个问题准备好。这些追问逻辑在小红书的笔试和面试中都有可能出现。3. 性能优化与常见问题排查笔试中的实战能力考察3.1 内存泄漏高频考点的识别、定位与修复性能优化是Android笔试和面试中占比不小的一块而内存泄漏又是其中的绝对核心。小红书这套题在内存泄漏的考察上非常务实它不要求你背一堆概念而是给你代码场景让你判断是否有泄漏风险以及如何解决。常见的内存泄漏场景可以整理成一张清单泄漏场景原因解决方案非静态内部类持有Activity引用内部类隐式持有外部类引用改为静态内部类WeakReferenceHandler消息未移除MessageQueue持有Handler引用onDestroy时removeCallbacksAndMessages静态变量持有Context静态引用生命周期过长使用ApplicationContext未取消注册的监听器观察者模式中观察者未移除onDestroy时unregister单例持有Activity引用单例生命周期与应用一致传入Context时使用ApplicationContext资源未关闭IO流、Cursor等占用内存try-with-resources或finally中close我在实际项目中最常踩的坑是单例模式持有Activity引用。比如一个全局的定位管理类用静态方法传入Activity用于弹窗如果不小心把Activity存成了成员变量页面退出后就会造成泄漏。这种问题在LeakCanary出现之前几乎只能靠人工Review和压测去发现。笔试中对内存泄漏的考察通常会附带HashMap和集合类相关的题。比如一个静态HashMap持有Activity引用即使你做了移除操作如果没有把Activity本身从Map中移除它依然无法被回收。同理匿名内部类如果做耗时操作但没有取消也会在Activity销毁后继续存活。这类题目的核心逻辑是只要对象的生命周期长于它引用的对象就可能产生泄漏。3.2 ANR与卡顿从原理到定位手段全解析ANRApplication Not Responding是Android系统对应用无响应的提示也是笔试中的常见考点。要理解ANR就要先理解系统判定ANR的几个触发条件。Activity的onCreate和onResume如果在5秒内没有完成广播的onReceive如果超过10秒Service的onCreate和onStartCommand如果超过20秒系统就会弹出ANR对话框。但仅仅记住这些数字是不够的小红书这类大厂的笔试题一定会进一步追问为什么主线程超时会触发ANR实际开发中如何避免和排查答案的核心在于消息机制。主线程执行的所有操作本质上都是Handler消息如果消息队列中某一个消息执行超过了限定时间后续的消息被阻塞系统就会判定ANR。所以避免ANR的本质是保证主线程消息能够及时执行完毕不要在UI线程做IO操作和复杂计算。排查ANR的常用手段包括查看/data/anr/traces.txt文件、使用Android Studio的Profiler分析主线程执行情况、在代码中监控消息队列的执行耗时。这里我分享一个排查经验ANR发生时traces.txt文件中往往能看到主线程的栈信息重点关注是否有锁竞争、死锁或者某个方法耗时过长。如果在主线程中调用了Thread.sleep或者使用了同步锁几乎一定会导致ANR。卡顿问题的考察角度和ANR类似但更偏向于渲染层面。这里面的核心概念是掉帧一帧画面需要在16.6ms内完成绘制如果超过了就会掉帧用户感知为卡顿。可能造成掉帧的操作包括过度绘制、布局层级过深、在onDraw中做了复杂逻辑、主线程做了耗时操作、GC频繁导致卡顿。笔试题中如果给出具体场景一般会让你分析问题成因并给出优化方案。3.3 RecyclerView的缓存复用原理从使用到源码级理解RecyclerView在Android开发中的使用频率极高也是大厂笔试中“看起来基础、实际上深度很大”的知识点。小红书这套题中RecyclerView相关的题目不仅停留在用法层面而是深入到缓存复用原理这恰恰是区分普通使用者和深入理解者的分水岭。先按层级来拆解RecyclerView的缓存机制。第一层是mAttachedScrap用于屏幕内ViewHolder的直接复用第二层是mCachedViews默认容量为2用于刚移除但可能马上回来的ViewHolder第三层是mRecyclerPool通过key来索引不同ViewType的ViewHolder池默认容量为5。这个三级缓存的设计意图是优先从最近的缓存中取用减少重新绑定和创建的开销。笔试中关于RecyclerView的高频考点有两个。第一个是getItemViewType的作用它决定了ViewHolder创建和复用的粒度。如果你在一个列表里混排了图片、文字、视频等各种item没有正确实现getItemViewType就会出现布局错乱的bug。第二个是notifyDataSetChanged和DiffUtil的区别这是从“能用到”到“用得好”的分水岭。notifyDataSetChanged会让整个列表刷新性能差且动画丢失DiffUtil会通过计算新旧列表的差异进行最小粒度的刷新。我在实际项目中踩过的坑是item内有EditText时滑动复用会导致输入内容串位。解决方案是在onBindViewHolder中保存每个item的文本状态同时在Adapter中设置setHasStableIds(true)确保ViewHolder的复用不会引起内容错乱。这类实操经验在笔试中可能不会直接出现但在面试追问环节非常加分。4. 网络、数据存储与Kotlin协程笔试中的热点方向4.1 网络框架与数据解析从HTTP到Retrofit的完整链路网络请求是移动应用的刚需也是笔试中的常客。要应付这部分的题目光会调用Retrofit是不行的你需要理解从HTTP协议到底层Socket的完整链路以及Android网络框架的演进逻辑。先看HTTP协议本身。笔试中高频考察的包括HTTP与HTTPS的区别、HTTPS的TLS握手流程、HTTP 1.0/1.1/2.0的核心差异、GET和POST的区别以及HTTP协议层面它们本质的作用。这里有一个常见的误区很多人以为GET和POST只是参数位置不同、长度限制不同但实际上在HTTP语义中GET用于获取资源POST用于提交数据处理在Restful架构中两者有明确的职责边界。然后是Android网络框架的演进。从早期HttpURLConnection和HttpClient并存到OkHttp逐渐成为事实标准再到Retrofit做接口层封装这个演进过程体现了一个核心趋势网络库越来越侧重于连接复用和性能优化。OkHttp的核心优势在于连接池复用、请求队列、拦截器机制、GZIP压缩、缓存策略等。笔试题中常会让你分析OkHttp的拦截器链结构ApplicationInterceptors → RetryAndFollowUpInterceptor → BridgeInterceptor → CacheInterceptor → ConnectInterceptor → NetworkInterceptors → CallServerInterceptor。数据解析方面JSON解析是基本功。Gson和Moshi基于反射Kotlin Serialization支持编译期生成代码性能更好。笔试中可能会问到一个经典问题为什么Swift的JSONEncoder性能比很多第三方库好答案在于Swift原生支持Codable协议编译期可以做类型检查运行时开销更小。4.2 数据存储方案选型从SharedPreferences到Room数据存储方向笔试常考的是不同存储方案的适用场景和优缺点对比。SharedPreferences适合存储轻量级的键值对但它不适合存大量数据也不适合存结构化数据。且SP有个老问题commit是同步写盘会卡主线程apply是异步写盘但可能丢失数据。从Android 8.0开始Google逐步推动SP的替代方案现在有了DataStore。SQLite和Room是结构化数据存储的主流方案。Room在SQLite之上做了一层抽象提供了编译期的SQL检查、LiveData和Flow的响应式支持、以及更安全的线程模型。笔试中如果问“Room和原生的SQLiteOpenHelper有什么区别”一定要提到编译期SQL验证和与架构组件ViewModel、LiveData的良好配合。这里我提醒一个容易忽略的知识点不要把数据库操作放在主线程执行。Room默认不允许在主线程执行数据库操作如果你用SQLiteOpenHelper系统不会主动拦截但实际使用中会因为主线程IO导致卡顿甚至ANR。笔试中有一个经典场景在ListView的getView中直接查询数据库刷新item这个场景几乎必然导致卡顿因为getView在主线程执行而数据库查询是耗时操作。4.3 Kotlin协程与Jetpack2020年笔试中的新趋势2020年是Kotlin协程在Android开发中大力普及的一年小红书这套题已经有所涉及。协程要掌握的核心点包括suspend挂起函数的原理、协程调度器Dispatchers.Main、IO、Default的区别、结构化并发与协程作用域、withContext与async/await的使用场景。很多同学对协程的理解停留在“比回调好用”的层面但笔试和面试更深层的追问是协程到底是怎么实现挂起的挂起函数在编译后发生了什么答案的关键是CPS变换。Kotlin编译器会把挂起函数编译成一个Continuation对象每次挂起点都是一次状态机状态流转。如果你能理解这一点就能解释为什么协程能实现非阻塞挂起线程在执行到挂起点后直接返回不占用线程等恢复时机到来时再通过指定的调度器切换线程继续执行。Jetpack方面ViewModel和LiveData是2020年笔试访谈的重头戏。ViewModel的核心价值在于将UI数据与界面生命周期解耦当Activity因配置变更重建时ViewModel不会跟着销毁而是通过ViewModelStore保存和恢复。LiveData则提供了一种可观察的数据持有者它感知生命周期只在活跃状态下分发数据从而避免内存泄漏和空指针。这里我补充一个实战经验ViewModel和协程结合使用时要特别注意viewModelScope的生命周期。viewModelScope会在ViewModel被清除时自动取消协程但如果你在ViewModel中直接创建了GlobalScope协程它不会随ViewModel销毁而取消这就会产生一个很大的坑协程持有ViewModel引用导致ViewModel无法被回收进而导致整个页面泄漏。5. 综合设计题与备战心得从笔试到面试的完整路径5.1 综合设计题的答题框架从需求分析到方案落地小红书这套卷子的末尾通常是开放性的综合设计题这部分的答题逻辑和前面完全不一样。它不考死记硬背的知识点而是考察你把零散知识点组织成一个完整架构的能力。常见的题目类型包括设计一个图片加载框架、设计一个IM消息列表、设计一个App启动优化方案、设计一个可复用的网络缓存策略等。这类题目的答题框架我总结了四个步骤第一步是需求分析。先把题目的功能需求和非功能需求都列出来。所谓功能需求就是“这个组件要对外提供哪些能力”非功能需求包括性能指标响应时间、内存占用、稳定性异常处理、降级策略、可维护性模块划分、接口设计等。这一步决定了后面所有设计的基调。第二步是架构分层设计。一般来说会分为UI层、业务层、数据层数据层再细分为内存缓存、磁盘缓存、网络源。以图片加载框架为例顶层是ImageLoader.load(url, imageView)对外API底层考虑LruCache内存缓存-DiskLruCache磁盘缓存-网络下载的加载链路中间还需要线程池管理、图片解码和压缩策略。第三步是关键技术点选型。比如缓存策略选择LRU还是LFU为什么图片解码用BitmapFactory还是第三方库线程池的初始参数怎么设定如何实现生命周期感知避免内存泄漏。每一个技术点的选择都要能说出理由而不是拍脑袋。第四步是风险预判和扩展性考虑。比如弱网环境下如何做重试图片加载失败如何降级如果需求从图片加载扩展到视频封面加载架构要怎么设计。能把方案讲出弹性和扩展空间是拿高分的关键。5.2 针对小红书笔试的备战策略与方法论针对小红书这套题以及同类大厂的Android笔试题我提供一个比较系统的备战思路。时间安排上建议留出三到四周的集中准备期。前两周以基础知识点串讲为主把Java基础、Android四大组件、Handler、View体系、网络、存储、Kotlin协程这些核心模块逐项过一遍第三周刷真题和模拟题重点练代码阅读题和综合设计题的手写能力第四周模拟面试场景输出自己的面经和答题框架。做题方法上我特别建议大家不要只看答案就完事一定要动手验证。比如启动模式混淆时在MainActivity里打日志运行程序看实际的执行顺序Handler机制没问题写一个小Demo验证同步屏障的效果内存泄漏用LeakCanary实测确认泄漏路径。动手验证过的知识在笔试题里遇到时你不仅是“知道”而是“有体感”。知识体系搭建上建议以Android开发者官网的Training和Reference为主干以主流技术博客和源码解析为辅线。尤其推荐读一读《Android开发艺术探索》和《深入理解Android内核设计思想》前者偏实战后者偏原理两者配合可以形成一个比较好的知识框架。5.3 写在最后Android学习中的个人经验谈走到这里我想分享一些我在备考和实际写代码过程中的真实体会。Android开发是一个很吃基础的领域它不像后端可以做很纯粹的业务开发也不像前端可以比较快地做出炫酷的视觉效果。它的复杂度恰恰来自那层中间地带既要理解操作系统层面的进程和内存管理又要处理业务层面的复杂交互和性能问题。我见过很多同学在准备笔试的时候把大量精力花在“背题”上。客观题可以背但代码阅读题和综合设计题靠背是不可能答出深度的。真正有效的方式是拿真实项目去练手或者是自己实现一个完整的模块、组件过程中遇到的所有问题都会倒逼你去查源码、看原理、做测试。我当年准备面试时用了两周时间手写了一个简易版的图片加载框架从LruCache到线程池到Bitmap压缩一步步实现做完之后再去刷笔试题很多以前觉得生涩的概念突然就通了。最后讲一个笔试中特别容易被低估的细节代码规范和命名。笔试的手写代码和面试的白板代码面试官都会看你的代码风格。变量命名是否语义化、是否处理了边界条件、是否有必要的注释、代码结构是否清晰这些都是加分项。写好代码不是表演给面试官看的而是你平时写代码习惯的自然呈现。养成好习惯早晚会带来回报。
返回列表