好未来移动端秋招笔试复盘:Android、iOS与跨端技术全解析 好未来秋招移动端开发岗第三批笔试说实话拿到通知的时候我还有点意外——前面两批的笔试时间都安排在了周日晚上的黄金档第三批却直接放到了周二下午而且题量明显比前两批听到的反馈要多。我当时在牛客上翻了翻前两批的帖子有人说Android岗位Handler和Activity启动模式出了不少题iOS那边则重点考了ARC和RunLoop但我实际做完第三批试卷之后发现这次的题目构成和前两批有明显的差异尤其是跨端方向的内容占比比预期高很多这让我挺意外的。下面我按考场的真实顺序把我记忆中还能还原的题目、我当时思考的过程、以及后来对答案时补充的知识点全部整理出来。题目细节和原卷肯定有出入但考察方向和关键点是有参考价值的打算投好未来或者同类教育科技公司移动端岗位的同学可以对照着查漏补缺。1. 考前摸底这套笔试试卷的时间分配与题型分布先说说整张试卷的结构。第三批笔试一共90分钟满分100分题型分布大概是这样的题型题量分值我的时间分配单选题15题30分20分钟多选题5题15分15分钟填空题5题10分10分钟编程题2题30分30分钟问答题/设计题1题15分15分钟这个分布放在校招笔试里算是中规中矩但有几个细节值得注意。首先是多选题占比不高不过选错一个就全错容错率比较低。其次是编程题两道题都是核心考察点分值直接占了30%这个比例在移动端岗位里属于偏高的——很多公司移动端笔试的编程题只有一道或者干脆用选择题带过好未来第三批明显更看重代码落地能力。还有一个容易被忽略的点是试卷底部会标注本科目考察方向Android/iOS/跨端基础知识、操作系统与网络基础、数据结构与算法、工程实践能力。这个标注非常重要它基本划定了复习范围比盲目刷LeetCode有效得多。从知识模块来拆解的话我粗略统计了一下选择题和填空题里面操作系统和计算机网络大概占了40%移动端原生知识占了35%数据结构和算法占15%剩下10%是Vue等跨端框架的内容。这个比例和很多人的预期是反过来的——大家总觉得移动端笔试应该以Android或者iOS为主但实际上好未来这种教育科技类的公司非常看重候选人的计算机基础功底操作系统和网络的知识点比重特别大。这一点我在笔试前是没料到的我复习的重点主要压在了Activity启动模式、Handler机制、iOS的RunLoop这些纯移动端知识上结果考试时发现不少选择题其实考的是进程线程调度、TCP三次握手、DNS解析过程这类基础内容。好在这些知识我平时项目里接触过勉强能应付但如果准备时间充裕真的建议把操作系统和计算机网络的核心概念好好过一遍这个投入产出比很高。2. 原生移动端题目背后的基本功考察从Activity到RunLoop的踩坑点2. 原生移动端题目背后的基本功考察从Activity到RunLoop的踩坑点2.1 Android部分的几道关键题目还原与解析第三批笔试的Android题目给我印象最深的是三道题。第一道是单选题考察Activity的启动模式。题目给出了一个场景MainActivity是standard模式A是singleTopB是singleTaskC是singleInstance然后问依次启动MainActivity → A → B → C → A之后当前任务栈里存在的Activity实例有哪些。这道题我当时差点选错因为很多人都知道singleTask会清掉栈顶的Activity但容易忽略一个细节MainActivity是standard模式从MainActivity启动singleTask的B时系统会先查找任务栈中是否已有B的实例如果没有就创建但SingleTask启动时如果发现栈里已经有该Activity的实例会把这个实例之上的所有Activity清除掉。这道题真正的坑点在于最后一步从C启动AC是singleInstance它有自己的独立任务栈所以从C启动A时A会进入C所在的任务栈而不是MainActivity原来的任务栈这就导致整个任务栈的结构变得非常复杂。第二道题是Handler机制的填空。题目问的是当一个Message被dispatch之后它会被回收并放入____池中进行复用。答案是MessagePool也就是Message.obtain()复用的那个消息池。这个知识点看似简单但很多人只是机械地知道Handler要配合Looper使用不知道消息回收复用机制。这里其实隐含了性能优化的思路——Android系统在消息频繁创建销毁的场景下通过消息池来减少对象创建的开销。我实测过在没有使用obtain()的情况下一个高频倒计时的页面每秒钟会多创建好几个Message对象时间长了GC次数明显增加。所以面试时候如果能主动提到Message.obtain()机制通常会让面试官觉得你了解底层原理。第三道题是一道典型的线程通信设计题。题目给了一个场景在一个Android应用中主线程需要从网络获取用户信息然后更新UI要求写出你认为最合适的实现方式。这是一个开放性问题可以用Handler Looper、也可以用AsyncTask现在已经废弃了、还可以用协程。我选择了协程方案因为这是目前Android开发的主流做法。题目虽然开放但考官大概率希望看到候选人能解释为什么选择某种方案而不只是贴代码。我当时写的是用ViewModel LiveData Coroutine的组合解释了一下为什么协程比Handler更轻量为什么LiveData可以避免内存泄漏。这题考察的其实是架构思维不只是API使用能力。2.2 iOS部分的核心考点ARC与RunLoop的联动关系iOS部分的题目同样考察得很深。有一道选择题问的是在ARC环境下以下哪种情况会导致对象无法被及时释放选项里有循环引用、Block捕获self、NSTimer持有target、CoreFoundation对象混用。这题的正确答案是全部都会。循环引用是老生常谈Block捕获self如果self又持有Block也会造成循环NSTimer持有target且没有invalidate的话target永远不会释放CoreFoundation对象在ARC下不会自动管理需要手动CFRelease。但这里有个意外之处——这道题在第三批笔试里是以多选题形式出现的意味着选错一个就全扣我估计很多同学在这道题上吃过亏。RunLoop的题目出的也很有水平。题目给了一段代码在主线程创建了一个NSTimer然后说这个Timer在用户拖动ScrollView的时候不会触发问为什么。答案是RunLoop在Tracking运行模式下Timer会被暂停。这题考察的不是单纯记RunLoop有哪几种模式而是对UIKit事件循环机制的理解。我当时答题的时候思路是RunLoop的Mode本质上是一个过滤机制ScrollView拖拽时RunLoop会切换到UITrackingRunLoopMode这个模式下默认的NSDefaultRunLoopMode里的Timer不参与调度所以Timer就会卡住。这里有个很容易被忽略的细节Timer只有在被添加到RunLoop的某个Mode下才会生效如果直接使用scheduledTimerWithInterval方法它默认添加的是NSDefaultRunLoopMode。所以解决这个问题的标准方案是把Timer加到NSRunLoopCommonModes里这样它在Tracking模式下也能正常触发。顺便说一句iOS题目里还有一道关于内存分级的填空题问的是当系统内存紧张时系统会先回收哪种类型的应用内存我填的是后台应用的可清除内存。其实准确说法是iOS系统的内存回收顺序大致是从后台不活跃应用的可清除页面再到 suspended 状态的应用最后才是前台应用但这个题目是填空题差不多把概念写对就能拿到分。2.3 原生题目复习时的两条经验现在回想起来第三批笔试的原生题目难度其实并没有超纲但考察方式非常底层。它不直接问Activity有几种启动模式这种概念题而是给一个具体场景让你分析任务栈的变化。所以我在复盘时总结了两条经验。第一条复习Android知识时一定要结合场景-机制-原理三层来理解。比如知道Activity的启动模式分类这只是记忆层能解释singleTask清除栈顶Activity的时机这是机制层能理解任务栈的归属关系和Affinity的匹配逻辑这是原理层。笔试和面试真正拉开差距的是最后这一层。第二条iOS的知识复习不要孤立地背API要把ARC、RunLoop、多线程、内存管理这些东西串起来看。比如ARC和RunLoop看起来是两个模块但NSTimer的例子就把它们串联在了一起。我当时复习时做了知识点的关联图把内存管理和系统机制相关的概念用箭头连起来效果确实比线性刷题好很多。3. Vue与跨端技术题目好未来笔试里为什么会出现前端框架3.1 第三批笔试中Vue相关题目的实际占比与考察意图这里要重点说一下因为第三批笔试里Vue相关的题目占比比我预想的高不少甚至可以说如果你完全没有接触过Vue这部分可能丢掉10分左右的分数非常可惜。题目大致包括两道选择题和一道填空题。选择题考的是Vue响应式原理和数据绑定填空考的是Vue生命周期。很多人看到这里可能会疑惑一个移动端开发岗位的笔试为什么考Vue其实好未来内部的App开发现在大量采用了跨端方案尤其是学而思网校这类业务需要同时覆盖Android、iOS和小程序端Vue技术栈在跨端开发里是能够落地的。React Native、Flutter虽然也都在用但Vue在团队现有的跨端架构里位置特殊笔试出现Vue题目其实是团队技术选型的真实映射不是随便出题凑数的。说到这里我必须提一句热词里出现的好用的移动端vue开发框架——我在笔试前刚好研究过这个方向当时看到热词就去了解了一下。移动端Vue开发框架里比较主流的有uni-app、Weex、Vant等uni-app是基于Vue语法的跨端框架可以通过一套代码编译到App、小程序、H5等多个平台Vant是移动端组件库搭配Vue使用非常广泛。好未来第三批笔试考Vue大概率就是因为团队的跨端项目实际用到了类似的技术栈所以笔试才会专项考核。3.2 Vue响应式原理题目的答题思路与易错点那道Vue响应式选择题大概是这样的在Vue 2中以下哪种方式修改对象属性不会触发视图更新A、this.obj.name newNameB、this.$set(this.obj, name, newName)C、this.obj { ...this.obj, name: newName }D、Vue.set(this.obj, name, newName)。正确答案是A因为在Vue 2中普通对象添加新属性或者修改未经过Object.defineProperty处理的属性不会触发依赖收集和派发更新。但这里有个陷阱——如果obj的name属性在data中已经声明过了那么this.obj.name newName其实是能触发更新的。题目没有明确说明name属性是否最初就存在所以答题时要特别注意题干细节。我当时在这道题上犹豫了很久因为平时的项目经验里直接在data中声明好所有属性是标准做法很少会遇到动态添加属性的场景。后来我选对了但靠的是对Vue 2响应式原理的理解——Vue 2是用Object.defineProperty拦截属性的getter和setter这个拦截是逐属性处理的。所以只有在对象初始化时就已经存在的属性才会被拦截动态添加的新属性不具备响应式能力。这也正是Vue.$set存在的意义它会在目标对象上重新定义一个新属性的getter和setter让后续的赋值操作也能触发视图更新。这道题在移动端笔试中出现其实也反映了实际开发中的一个痛点在ToC的移动端项目里后端接口返回的数据结构经常会有动态字段如果直接用接口数据给data赋值容易出现数据变了但UI不刷新的问题。我当时项目里就踩过这个坑用一个对象存储用户行为日志行为类型是动态的结果上线后发现部分日志字段在前端展示不出来后来就是通过this.$set解决的。3.3 生命周期题目的连环坑与实战关联Vue生命周期的填空题考察的是执行顺序创建阶段beforeCreate → created、挂载阶段beforeMount → mounted、更新阶段beforeUpdate → updated、销毁阶段beforeDestroy → destroyed。这道题的坑点在于题目不是简单地让你填顺序而是给了一个场景在created钩子中请求数据在mounted钩子中操作DOM问这两个钩子执行的先后顺序以及原因。这个场景其实非常贴近真实开发。created中发请求是常见的做法因为此时data已经初始化可以对数据进行操作但DOM尚未生成mounted后DOM已经渲染完毕可以进行DOM操作。我答题时补充了一点——从created到mounted如果页面数据比较复杂中间的时间差可能会导致用户看到白屏或者loading状态所以通常会在created阶段就把loading状态设置好而不是等到mounted再处理。还有一道有关Vue移动端适配的题目让我印象很深刻。题目问的是移动端H5页面如何做屏幕适配选项里有rem、vw/vh、媒体查询、栅格系统。这道题本身不难关键是它出现在移动端开发岗的笔试里说明出题人希望候选人不仅会写Vue组件还要知道在真实移动端环境中怎么处理尺寸适配。我的答题选的是rem vw组合方案然后提了一句设计稿标注的宽度和实际屏幕宽度的换算逻辑。这种题目答起来其实挺加分的因为它体现了你对移动端真实环境的理解。3.4 跨端技术栈的拓展思考不只是会Vue语法考完Vue这部分之后我做了一个简单的技术栈总结整理了一下好未来移动端笔试可能涉及的跨端技术范围。这些内容不一定每道题都考但笔试题目频次最高的几个方向我可以列出来给大家做一个参考Vue 2/3的响应式原理和数据双向绑定机制Vue生命周期及其在移动端页面中的应用页面加载、数据请求、组件销毁时的资源释放移动端尺寸适配方案rem、vw、rpx的原理与换算uni-app等跨端框架的配置与平台差异处理组件间通信props、事件总线、Vuex/Pinia状态管理这里我想特别说一下组件间通信。笔试虽然没直接出题但问答题里有一道涉及多个页面共享登录状态的设计题我答题时用到了Vuex的状态管理思路。这道问答题我放在后面详细讲但它和Vue的关联非常紧密——在移动端跨端项目里不同平台之间的状态同步问题本质上和Vuex解决的前端状态共享问题是同构的。4. 工程能力与算法题笔试中最容易被低估的拉分项4.1 两道编程题的完整复现与解法分析编程题总共两道第一道是常规的算法题题目描述是给定一个整数数组和一个目标值target找出数组中三个数相加之和与target最接近的组合返回这三个数的和。这是LeetCode 16题的变体难度不高但笔试时要求用Java或者Kotlin手写完整代码和平常在IDE里做题的感觉完全不同。我当时的解法是排序 双指针。排序之后固定一个数然后用双指针在剩余区间内逼近target。这个解法的时间复杂度是O(n²)空间复杂度O(1)。笔试环境没有本地IDE提示所以手写代码时最需要注意的就是边界条件——数组长度不足3时要直接返回指针移动时要避免重复组合。我后来查了查这道题的标准解法就是排序 双指针代码大概这样public int threeSumClosest(int[] nums, int target) { Arrays.sort(nums); int best nums[0] nums[1] nums[2]; for (int i 0; i nums.length - 2; i) { int left i 1; int right nums.length - 1; while (left right) { int sum nums[i] nums[left] nums[right]; if (Math.abs(sum - target) Math.abs(best - target)) { best sum; } if (sum target) { left; } else if (sum target) { right--; } else { return target; } } } return best; }这道题在移动端岗位笔试中出现我认为不是为了让候选人去做复杂的算法竞赛而是考察代码的基本功和逻辑严谨性。移动端日常开发中处理数组、列表数据时经常会用到左右指针的思路比如双端队列的实现、滑动窗口等所以这种题对实际开发是有直接助益的。第二道编程题是移动端场景题。题目要求设计一个简单的LRU缓存类支持get和put操作缓存容量固定超出容量时淘汰最久未使用的数据。这道题对于移动端开发来说非常熟悉因为图片加载库比如Glide、Fresco里的内存缓存就大量使用了LRU算法。我当时的实现思路是HashMap 双向链表。用HashMap保证O(1)的查询效率用双向链表维护访问顺序每次get时把访问的节点移到链表头部每次put时如果超过容量就淘汰链表尾部的节点。这里有一个关键点线程安全。笔试环境虽然不会真的跑并发测试但面试官在看代码时一定会注意你是否考虑了多线程场景。我当时在类中加了一个ReentrantLock把get和put方法都加锁了这可能是我这道题拿到不错分数的原因之一。class LRUCache { private int capacity; private MapInteger, Node map; private Node head; private Node tail; private ReentrantLock lock new ReentrantLock(); public LRUCache(int capacity) { this.capacity capacity; map new HashMap(); head new Node(0, 0); tail new Node(0, 0); head.next tail; tail.prev head; } public int get(int key) { lock.lock(); try { if (!map.containsKey(key)) { return -1; } Node node map.get(key); moveToHead(node); return node.value; } finally { lock.unlock(); } } public void put(int key, int value) { lock.lock(); try { if (map.containsKey(key)) { Node node map.get(key); node.value value; moveToHead(node); } else { Node node new Node(key, value); map.put(key, node); addToHead(node); if (map.size() capacity) { Node tailNode removeTail(); map.remove(tailNode.key); } } } finally { lock.unlock(); } } }这道题做完之后我有个感悟——移动端笔试的算法题重点不太在于题目本身有多难而在于候选人能不能写出工程级的代码。什么叫工程级就是要考虑边界情况、考虑线程安全、考虑代码的可读性。很多同学在刷LeetCode时习惯性地只写核心逻辑但笔试是有追问的面试官看到注释清晰、结构完整的代码印象分会高很多。4.2 问答题的设计思路数据库缓存 网络请求的整体架构问答题是一道设计题题目内容大致是在移动端App中为了实现离线阅读功能需要对资讯列表数据进行本地缓存同时需要支持下拉刷新获取最新数据请设计一个完整的缓存与请求策略并解释为什么这样设计。这题我觉得是整张试卷里最贴近实际工作的一道题。我当时的设计思路是分层双缓存策略核心是三段式结构内存缓存 → 磁盘缓存 → 网络请求。内存缓存用的是LruCachekey是请求的URL或者接口方法名value是解析后的数据模型这样可以保证用户在一次App运行周期内快速读取数据。磁盘缓存用的是Room数据库因为Room是Google官方推荐的ORM库支持协程和Flow做本地持久化非常方便。网络请求用的是Retrofit OkHttp用Interceptor做了一层缓存拦截——当网络不可用时直接返回磁盘缓存的数据。我解释设计理由的时候特别强调了几个点。第一为什么需要两级缓存而不直接用磁盘缓存因为磁盘IO的速度虽然比网络快但和内存相比还是慢了一个数量级在很多需要频繁读取同一个数据的场景里比如滚动列表时反复加载同一页数据内存缓存能明显减少卡顿。第二为什么下拉刷新时要使用先展示缓存再静默请求的策略因为这样用户感知到的速度更快体验更好。这是移动端开发里一个很重要的交互原则——不要让用户等网络请求完成才能看到数据。当时我在答题纸上画了一个简单的数据流向图用文字描述大概是这样的用户打开页面 → 内存缓存有数据 → 立即展示 → 同时后台请求网络 → 网络返回 → 更新内存和磁盘缓存 → 刷新UI。如果内存缓存没有数据 → 查磁盘缓存 → 有数据 → 展示 → 请求网络更新没有数据 → 直接请求网络 → 加载loading → 返回后写入缓存再展示。这种设计思路其实不止适用于资讯类App电商、社交、工具类App的列表页几乎都是这个模式。好未来笔试考这道题我认为是在考察候选人的整体架构意识看你有没有思考过移动端数据层怎么设计才健壮、怎么缓存策略才能兼顾速度和新鲜度。4.3 工程题透露出的人才要求这套题做完之后我能明显感觉到好未来对移动端开发岗的定位不只是会写页面的工程师而是需要具备以下三种能力。第一种是数据与状态管理能力。从选择题和编程题都能看出无论是Vue的响应式、还是LRU缓存、还是问答题的缓存策略本质上都在考察数据怎么流动、怎么存储、怎么同步的问题。移动端App的核心竞争力其实就在数据层谁能把数据操作做得又快又稳谁就能做出更好的用户体验。第二种是场景化思维。整套试卷几乎没有一道题是纯粹考概念的所有题目都包装在具体场景中。Activity启动模式对应的是页面跳转异常RunLoop对应的是Timer不准Vue响应式对应的是移动端页面数据更新异常LRU对应的是图片缓存设计。这种出题风格要求候选人复习时不能死记硬背一定要理解每个概念在真实应用中的触发条件和表现。第三种是跨端视野。笔试里出现Vue相关内容加上问答题里涉及的跨平台状态同步问题说明这个岗位实际工作中一定会接触到跨端开发。如果你只懂Android或者只懂iOS虽然也可以通过笔试但面试时的竞争力会弱不少。5. 复盘梳理第三批笔试的隐藏筛选逻辑与备考建议5.1 藏在题目背后的三层筛选逻辑笔试全部结束之后我花了大概一个晚上复盘把整张试卷的题目归类了一下发现这些题目背后其实隐藏着非常清晰的三层筛选逻辑。第一层是基础层筛选对应的是操作系统、计算机网络、数据结构这些计算机基础题目。这一部分题目分值最高但难度不大只要系统学过计算机基础课程的都能拿到分。这层筛选的目的是筛掉没有受过系统训练的候选人。虽然移动端开发看起来偏应用层但好未来这种体量的公司依然非常看重候选人的基础功底因为移动端底层很多问题内存管理、进程通信、性能优化都需要基础知识的支撑。第二层是专业层筛选对应的是Android/iOS的知识点和Vue等跨端内容。这层主要筛掉简历写了精通移动端但实际只做过简单页面的候选人。举个典型例子Activity启动模式的题目如果你只是背过四种启动模式的定义遇到实际场景题就很容易出错因为真实的启动逻辑受Intent Flag、TaskAffinity、启动方式等多重因素影响不是背几个概念就能搞定的。这层筛筛选的其实是真实项目经验。第三层是潜力层筛选对应的是两道编程题和问答题。这一层不是筛掉谁而是筛出谁——筛出那些具备良好工程习惯、有架构思维、能够主动思考为什么的候选人。LRU的线程安全设计、缓存策略的分层设计这些内容在标准答案里不是必须项但如果你主动做了就会明显拉开和其他候选人的差距。5.2 我给后续备考者的具体建议结合第三批笔试的实际体验我给准备投好未来或者类似教育科技公司移动端岗位的同学几条具体建议。第一时间分配上基础科目要提前过一遍不要临考突击。我去考试之前一直在刷Android知识操作系统和网络这些科目基本是裸考状态结果选择题里很多基础题我都要靠着平时的零散记忆来猜。如果准备时间有限建议优先过一遍进程与线程、死锁条件、TCP/IP握手挥手、HTTP与HTTPS的区别这几个高频考点它们既是选择题的常客也是后面编程题和问答题的知识基础。第二移动端原生知识的复习一定要结合场景题来练。你可以找一个在线题库专门练习Activity启动模式场景分析、Handler消息机制流程分析、RunLoop模式切换这类题。做题的时候不要只求选出正确答案要把整个推导过程在草稿纸上画出来这样才能加深理解。我曾经用一小时专门把Activity任务栈的内容画了一遍后面再做任何启动模式的题都不慌了。第三跨端技术栈尤其是Vue相关内容有条件的话一定上手做一个小项目。不需要多复杂一个能够展示列表、点击跳转、数据状态共享的简单H5页面就够了。做这个项目的目的不是让你成为前端专家而是让你真正理解Vue的响应式、生命周期、组件通信这些核心概念。笔试的Vue题目其实考得很浅只要真正做过一个项目基本都能答上来但如果你完全没碰过Vue临时抱佛脚背概念很容易在细节上翻车。第四编程题的刷题方向建议以高频算法 工程类算法为主。高频算法就是LeetCode 1、15、16、146这些经典题目反复刷刷到能够手写不卡壳为止。工程类算法则是LRU、LFU、线程池、生产者消费者模型这类与实际开发相关的题目这些题在移动端面试中出现频率特别高而且回答的时候可以从工程角度增加亮点。5.3 备考时的资源清单与工具推荐最后整理一份我备考时觉得好用的资源不一定全面但都是我实际用过并且觉得有价值的。算法练习LeetCode热门100题 剑指Offer重点刷数组、链表、二叉树、动态规划这几类移动端笔试最常见的就是这些。Android知识官方文档的Application Fundamentals部分加上《Android开发艺术探索》里关于Handler、Activity启动模式、消息机制的章节这本书虽然有点年头了但底层原理讲得依然到位。iOS知识官方文档的Memory Management和RunLoop相关章节配合一篇经典的RunLoop深度解析博客来理解效果很好。Vue与跨端uni-app官方文档搭一个小DemoVue 2的响应式原理看官方文档的深入响应式原理那一节就够了不用过度深入源码。面试经验牛客网上好未来移动端岗位的面经和笔经看近一年的帖子了解最新的出题变化。我看的时候发现前两批笔试的帖子对第三批的参考价值不小尤其是题型分布的反馈基本准确。备考的时候还有一个小技巧准备一本笔记本把每次做题时遇到的模糊知识点记下来然后集中查漏补缺。我当时在刷题时发现自己对HTTP缓存策略这个知识点掌握得很差就单独花了一个下午仔细研究了一遍强缓存和协商缓存的区别结果第三批笔试里恰好有一道关于缓存策略的问答题知识点算是现学现用了。笔试只是整个秋招流程的第一步通过之后还有面试环节。但笔试的准备过程本身就是一次系统性的知识梳理把操作系统、网络、移动端基础、跨端框架、算法这些内容串联起来形成了一个相对完整的知识框架这个框架到面试时还能继续发挥作用。我整理这份复盘内容也是希望后来者能少走一些弯路把有限的准备时间花在真正的重点上。