復(fù)習指南)
聊 Android 面試這件事我踩過的坑大概比很多人想象得要多。前幾年我自己跳槽那陣子簡歷投出去石沉大海復(fù)盤時才發(fā)現(xiàn)問題根本不在題背得夠不夠多而在我講不清楚一件很樸素的事——這個方案當初為什么選它。后來我陸續(xù)幫幾個學(xué)弟學(xué)妹做過模擬面試去年秋天一個準備轉(zhuǎn) Android 方向的學(xué)妹拿到了心儀的大廠 offer把她三個多月整理的復(fù)習筆記丟給我看我才意識到真正有效的 Android 面試準備是一套能力映射的工程而不是一份題目清單。這份筆記加上我自己這些年做技術(shù)面試官的經(jīng)驗基本覆蓋了一個 Android 崗位從簡歷篩選到終面的大部分考察面。不管你是剛學(xué)完 Android Studio 環(huán)境搭建、能跑通一個增刪改查的 App還是已經(jīng)寫了兩三年業(yè)務(wù)代碼想更進一步下面這些內(nèi)容都能直接拿去對照補漏。我不會給你一份必背一百題而是按面試官到底在聽什么這個角度把每一塊該講的深度都拆開。1. 先別急著背題Android 面試真正篩的是什么能力1.1 面試官手里那張看不見的評分表絕大多數(shù)人準備面試的方式是打開一個題庫文檔從第一題開始往下刷。這個方式不是沒用但效率極低因為它假設(shè)了問題和能力是一一對應(yīng)的。實際上面試官手里通常是一張相對模糊的評分表大致分成四欄基礎(chǔ)扎實度、工程判斷力、表達與溝通、成長潛力。同一道說說 Handler 機制的題不同的人答出來落點可能完全不同——有人背出了 MessageQueue 和 Looper有人能講清楚主線程為什么阻塞在 native 層的 epoll 上卻不觸發(fā) ANR還有人能順帶說出自己在項目里怎么用 IdleHandler 做延遲初始化。這三個答案在評分表上的位置是遞增的。我后來跟那位學(xué)妹聊她面試中的實際感受她說最有用的一個轉(zhuǎn)變是把我要答對這道題改成我要讓面試官相信我能獨立負責一個模塊。這個轉(zhuǎn)變聽起來虛但落地方式很具體每講一個知識點盡量帶上三個東西——它解決什么問題、它內(nèi)部大致怎么實現(xiàn)、我在真實項目里用它踩過什么坑。前兩個靠讀第三個只能靠做和復(fù)盤。如果你沒有足夠的項目經(jīng)歷去支撐第三點那就用我讀源碼時發(fā)現(xiàn)的或者我在一個小 demo 里驗證過的來替代至少證明你是動手驗證過的人而不是復(fù)述文檔的人。1.2 三類問題的時間配比與準備順序我把 Android 崗位的面試問題粗分成三類它們對應(yīng)完全不同的準備方式混在一起準備是最容易浪費時間的。問題類型典型形式考察重點建議投入精力基礎(chǔ)原理類Java/Kotlin 語法、Handler、Binder、View 繪制概念是否成體系有沒有自相矛盾40%工程實踐類性能優(yōu)化、崩潰排查、架構(gòu)選型有沒有量化意識和取舍能力40%場景與手撕算法題、設(shè)計題、現(xiàn)場寫代碼編碼基本功、思維清晰度20%很多人把 80% 的時間砸在第一類上結(jié)果被問到你那個啟動優(yōu)化到底省了多少毫秒、怎么測的就啞了。反過來說工程實踐類是最能拉開差距的地方因為它很難臨時背出來。我的建議順序是先用一兩周把基礎(chǔ)原理的骨架搭起來然后立刻轉(zhuǎn)到自己項目里找兩三個真實問題深挖最后臨考前兩周集中刷手撕題保持手感。1.3 我見過的兩種典型錯誤準備方式第一種是只背結(jié)論不留推導(dǎo)。比如你背下Android 的 GC 是并發(fā)復(fù)制收集器面試官追問一句那它和 HotSpot 的分代收集有什么區(qū)別為什么要這么設(shè)計你就卡住了。結(jié)論是可以查到的推導(dǎo)過程才能證明你理解。第二種是過度追求廣度。有人會去翻一大堆冷門 API覺得覆蓋面廣就穩(wěn)。但面試官通常只在他自己熟悉的領(lǐng)域深挖你把十個方向都講得浮在表面不如把三四個方向講到能畫圖、能寫代碼、能說出邊界條件。我個人的經(jīng)驗是準備二十個能講五分鐘的話題比準備兩百個能講三十秒的話題要有效得多。2. Java 與 Kotlin從能用講到為什么這么設(shè)計2.1 Android 上的運行時和標準 JVM 不是一回事這是被低估的一個話題。你如果只說Java 靠 JVM 跑有垃圾回收那基本等于沒說。Android 從 4.4 之后逐步切到 ART運行方式在 AOT 和 JIT 之間做過好幾輪調(diào)整理解這條演進線很多性能問題就自然解釋得通了。最早 Dalvik 是解釋執(zhí)行加 JIT安裝快、運行慢所以早期 Android 手機裝個 App 要等很久的優(yōu)化中其實是在做 dexopt。ART 上來之后改成安裝時全量 AOT運行快但安裝慢、占空間大。再往后引入 profile 引導(dǎo)的混合編譯先解釋執(zhí)行把熱點方法記錄下來設(shè)備空閑時后臺編譯這些熱點這樣就兼顧了安裝速度和運行效率。你如果能把這幾個階段和為什么要這么改講清楚面試官對你的評價會立刻不一樣。GC 也是同理。早期是標記清除加標記整理容易產(chǎn)生碎片和長時間停頓后來換成并發(fā)復(fù)制的方案把內(nèi)存分成多個區(qū)域并行回收停頓時間明顯縮短再后面引入分代思路針對大部分對象朝生夕死這個特點做優(yōu)化。這背后其實就是一句話移動端的 GC 目標不是吞吐量而是盡可能短的卡頓。你把這句話講出來比背一堆參數(shù)有用。2.2 線程池參數(shù)到底怎么算線程池幾乎是必問題但多數(shù)人停在核心線程數(shù)、最大線程數(shù)、隊列、拒絕策略這四個名詞上。面試官真正想聽的是你憑什么定這組參數(shù)。先說參數(shù)含義。任務(wù)進來時如果當前線程數(shù)小于核心線程數(shù)直接開新線程否則丟進阻塞隊列隊列滿了再嘗試把線程數(shù)擴到最大值還是滿了就走拒絕策略。這里面最關(guān)鍵、也最容易出問題的是隊列的選擇。用無界隊列的話最大線程數(shù)這個參數(shù)基本是廢的因為隊列永遠不