小米Android開發面試全記錄:Jetpack+性能優化+系統級開發全考察
3年Android開發經驗,詳細復盤小米三輪技術面試,涵蓋Kotlin協程、Jetpack全家桶、性能優化、內存洩漏排查、Binder原理、插件化框架等核心考點
背景介紹
先說下我的情況,211本科計算機專業畢業,在一家中型互聯網公司做了三年Android開發。雖然不是大廠出身,但項目經驗還算豐富——從0到1做過兩個App,也做過SDK開發。小米一直是我的Dream Company之一,畢竟是做MIUI起家的,Android開發的技術深度肯定不差。而且小米現在在造車,Android開發在車機端也有應用場景,感覺發展空間很大。
投簡歷是在小米招聘官網投的,大概五天後收到了HR的電話,約了一面時間。整個流程三週左右,三輪技術面+一輪HR面。下面詳細說說每輪面試的情況。
面試流程復盤
一面:Kotlin+Jetpack(約1小時)
一面面試官是個看起來很幹練的工程師,開場先讓我簡單介紹了一下工作經歷,然後直接開始技術問答。
第一個問題就讓我有點緊張:Kotlin的協程和Java的線程有什麼區別?協程的掛起是怎麼回事?我從輕量級、非阻塞、協作式調度幾個角度做了對比,然後講了suspend關鍵字和狀態機的關係——編譯器會把suspend函數轉換成狀態機,通過Continuation傳遞來實現的。面試官追問:withContext和async的區別?在什麼場景下用哪個?我說withContext是串行切換調度器,async是並行執行並等待結果,需要並行多個任務時用async,需要切換線程執行單個任務時用withContext。
Jetpack部分問得很細:ViewModel的生命週期是怎樣的?為什麼Configuration Change時ViewModel不會銷毀?我從ViewModelStore的角度解釋,ViewModel存在Activity的ViewModelStore中,而Configuration Change時Activity雖然會重建,但ViewModelStore會被保留。面試官追問:ViewModelStore是怎麼被保留的?這個我答得不太好,只說了通過NonConfigurationInstances機制,但具體實現細節記不太清了。面試官提示了一下是ActivityThread的retainNonConfigurationInstances方法,我表示確實沒看到這一層。
還問了:Room數據庫的Migration機制?、Navigation組件的深層連結怎麼實現?、DataStore和SharedPreferences的區別?這些都是Jetpack的常見考點,我基本都答上來了。
代碼題是:用Kotlin實現一個帶緩存的圖片加載框架的核心邏輯,要求支持內存緩存和磁盤緩存。這道題考察的是設計能力,我用了LruCache做內存緩存,磁盤緩存用DiskLruCache,加載流程是內存→磁盤→網絡的三級緩存。面試官讓我寫了內存緩存的核心代碼,包括LruCache的sizeOf方法重寫和緩存淘汰策略。
二面:性能優化+內存洩漏(約1.5小時)
二面是個做性能優化的專家,一上來就問我:你在項目中做過哪些性能優化?我從啟動優化、佈局優化、內存優化三個方面講了我們的實踐。
啟動優化那塊,我講了我們用systrace分析冷啟動耗時,發現Application的onCreate裡做了太多初始化,後來用有向無環圖做任務調度,把初始化任務按依賴關係並行化,冷啟動時間從3秒降到了1.5秒。面試官追問:有向無環圖的拓撲排序怎麼實現?如果存在循環依賴怎麼辦?我說用BFS實現,循環依賴在構建圖的時候檢測,如果發現有入度始終不為0的節點就說明存在循環。
內存洩漏部分是重點:常見的內存洩漏場景有哪些?怎麼排查?我從靜態變量持有Activity引用、內部類持有外部類引用、Handler的Message未移除、註冊的監聽器未反註冊幾個場景講起,排查工具講了LeakCanary和Android Studio的Memory Profiler。面試官追問:LeakCanary的原理是什麼?它是怎麼自動檢測內存洩漏的?我講了WeakReference+ReferenceQueue的機制,以及GC後如果WeakReference仍然存在引用鏈就說明有洩漏。
他還問了一個很有深度的問題:如果App在低端機上出現頻繁GC導致卡頓,你怎麼排查和優化?我說先用Memory Profiler看內存分配情況,找出分配頻率最高的對象,然後看能否減少分配——比如用對象池復用、避免在循環中創建對象、用基本類型代替包裝類型。面試官追問:對象池的實現有什麼要注意的?我說要注意池的大小控制,避免池本身成為內存洩漏源,還要注意多線程安全。
代碼題是:實現一個簡單的對象池,支持泛型,要求線程安全。我用ConcurrentLinkedQueue做對象存儲,用AtomicInteger控制池大小,寫了一個泛型對象池。面試官讓我考慮一下對象回收時的狀態重置問題,我說可以在回收時調用一個reset方法來清理對象狀態。
三面:系統級開發+項目深挖(約1.5小時)
三面是個資深架構師,問題更加宏觀和系統化。
他先問:你對Android的進程間通信了解多少?Binder的原理是什麼?我從Binder的C/S架構講起,說到ServiceManager、Binder驅動、內存映射,以及一次拷貝的高效性。他追問:Binder和Socket、管道、共享內存等其他IPC方式相比有什麼優勢?我對比了性能、安全性、易用性幾個維度,Binder在性能上僅次於共享內存,但安全性更好。
然後是項目深挖環節,他讓我講一個最有挑戰的項目。我選了之前做的插件化框架開發——我們用Hook Instrumentation的方式實現Activity的插件化加載。他問的問題非常刁鑽:Hook Instrumentation的時機是什麼?怎麼保證Hook的穩定性?、插件中的資源怎麼加載?資源ID衝突怎麼解決?、Android 9.0之後對反射的限制怎麼繞過?
資源ID衝突那塊我答得不太好,我們當時的方案是給插件的資源ID加一個偏移量來避免衝突,但面試官說這種方案在插件數量多的時候不夠靈活,建議了解一下AAPT2的資源ID分段機制。Android 9.0的反射限制那塊,我講了用元反射繞過——通過反射獲取反射的setAccessible方法來突破限制,但面試官說這個方案在高版本上可能失效,讓我關注Android最新的限制策略。
最後聊了大概20分鐘的技術方向,面試官介紹了小米在Android系統級開發上的一些探索,包括他們自研的MIUI優化框架和車機端的Android系統定制,聽起來確實很有技術深度。
真題彙總
1. Kotlin協程和Java線程的區別?協程掛起的原理?
2. withContext和async的區別和使用場景?
3. ViewModel的生命週期和ViewModelStore保留機制?
4. 實現帶緩存的圖片加載框架核心邏輯
5. 冷啟動優化方案?有向無環圖任務調度?
6. 常見內存洩漏場景和排查方法?LeakCanary原理?
7. 頻繁GC導致卡頓的排查和優化?
8. 實現線程安全的泛型對象池
9. Binder原理?和其他IPC方式的對比?
10. 插件化框架的實現?資源ID衝突解決?
心得建議
第一,Kotlin必須精通。小米的Android開發全面使用Kotlin,面試中Kotlin相關的題目佔比很大。尤其是協程,不能只停留在會用launch和async的層面,要理解底層的狀態機實現。
第二,Jetpack全家桶要熟悉。ViewModel、Room、Navigation、DataStore這些組件的原理和使用場景都要掌握,面試中會從使用問到原理。
第三,性能優化要有實戰。小米特別看重性能優化能力,啟動優化、內存優化、卡頓優化都要有實際經驗。光知道工具名字不行,得能講出具體的優化過程和效果數據。
第四,系統級知識是加分項。如果你了解Binder、AMS、PMS這些系統級知識,面試官會非常感興趣。尤其是做系統級開發的崗位,這些是必考內容。
第五,項目經驗要有深度。小米面試官很在意你是否真正理解項目的技術細節,而不只是用了什麼框架。每個技術選型的原因、踩過的坑、做過的優化,都要能說清楚。
FAQ
Q:小米Android開發的工作強度如何?
A:面試時了解到MIUI版本迭代期加班較多,但平時節奏還行。相比互聯網大廠,小米的工作強度算是中等偏上。
Q:對Kotlin有硬性要求嗎?
A:基本是硬性要求,小米Android開發全面使用Kotlin,面試中Kotlin題目佔比很大。
Q:面試結果多久出?
A:我是一面後4天約二面,二面後5天約三面,三面後一週出結果,整體大概三週。
Q:學歷要求?
A:Android開發崗本科就行,但985/211優先。有扎實的項目經驗比學歷更重要。
Q:薪資水平?
A:3年Android經驗,月薪大概在22-32k之間,總包在35-50w左右。小米的薪資在手機廠商裡算不錯的,而且股票激勵比較大方。