
寫在前面
在網際網路行業裡,2021年來到今天你能聽到的消息都是什麼樣的?
“某D公司開始裁員了”
“某A公司據說當機社招了”
“據說J公司今年沒有年終獎“
“據說M公司要裁員50%”
……
2020年是我過得最亂也是最快的一年,全年從開頭到結尾似乎就沒多少好消息。所有行業都受到了影響,直到今年也沒有完全恢複。而對于廣大Android開發者來說,找工作似乎也變得越來越難了。
2021年1月,我在51job搜尋了一下北京地區的Android崗位,隻有2100多個,而幾年前的時候,大概是2015年中期吧,我記得那時候Android崗位是過萬的(我應該沒有記錯),現在的形勢對Android developer如何可謂一目了然……
當然,經濟大環境如此,行業過冬,找工作難肯定不隻是Android獨有的,其他技術同行們肯定日子也難過,今天寫下這篇文章,主要是想把我整理的《2021Android面試題大全》分享給大家,部分章節放到知乎上已經獲得1000+的點贊,我會把領取方式放在文末,有需要的小夥伴可以免費領取。冬天嘛,要的就是一個抱團取暖喽。
PS:本文僅針對Android國中級工程師,如果你已經是進階工程師,甚至是業内小有名氣的牛人,那麼不看也罷,反正實力強的人找工作不會太難。
Android面試核心知識點精講
又到年底了,每到這個時候,我們都會慢慢反思,這一年都做了什麼?有什麼進步?年初的計劃都實作了嗎?明年年初有跳槽的底氣了嗎?況且今年的網際網路環境太差,需要自己有足夠的知識儲備,才能夠應對這淩冽的寒風。
1、Java 相關
- 容器(HashMap、HashSet、LinkedList、ArrayList、數組等)
需要了解其實作原理,還要靈活運用,如:自己實作 LinkedList、兩個棧實作一個隊列,數組實作棧,隊列實作棧等。
HashMap、HashTable 和 CurrentHashMap 的核心差別(并發),其次内部資料結構的實作、擴容、存取操作,再深一點 哈希碰撞,哈希計算,哈希映射,為什麼是頭插法,擴容為什麼是 2 的幂次等。
- 記憶體模型
參考連結
了解Java記憶體模型 你了解Java記憶體模型麼(Java7、8、9記憶體模型的差別)
- 垃圾回收算法(JVM)
JVM 類加載機制、垃圾回收算法對比、Java 虛拟機結構
當你講到分代回收算法的時候,不免會被追問到新生對象是怎麼從年輕代到老年代的,以及可以作為 root 結點的對象有哪些兩個問題。
- 談談對 JVM 的了解?
- JVM 記憶體區域,開線程影響哪塊區域記憶體?
- 對 Dalvik、ART 虛拟機有什麼了解?對比?
- 垃圾回收機制和調用 System.gc()的差別?
- 類加載過程(需要多看看,重在了解,對于熱修複和插件化比較重要)
- 反射
- 多線程和線程池
線程有哪些狀态,哪些鎖,各種鎖的差別
并發程式設計:
synchronized 和 volatile 、ReentrantLock 、CAS 的差別
synchronized 修飾執行個體方法和修飾靜态方法有啥不一樣。
sleep 、wait、yield 的差別,wait 的線程如何喚醒它
- HTTP、HTTPS、TCP/IP、Socket通信、三次握手四次揮手過程
計算機網絡部分:
- TCP 有哪些狀态
- 三次握手、四次揮手。為啥不是三次不是兩次
- HTTPS 和 HTTP 的差別,HTTPS 2.0 3.0?
- 浏覽器輸入一個 URL 按下回車網絡傳輸的流程?
- 問的深一點的可能涉及到網絡架構,每層有什麼協定,FTP 相關原理,例:TCP 建立連接配接後,發包頻率是怎麼樣的?
- 設計模式(六大基本原則、項目中常用的設計模式、手寫單例等)
1、生産者模式和消費者模式的差別?
2、單例模式雙重加鎖,為什麼這樣做?
3、知道的設計模式有哪些?
4、項目中常用的設計模式有哪些?
5、手寫生産者、消費者模式。
6、手寫觀察者模式代碼。
7、擴充卡模式、裝飾者模式、外觀模式的異同?
8、談談對 java 狀态機的了解。
9、談談應用更新(灰階、強制更新、分區更新?)
- 斷點續傳
- Java 四大引用
強引用、軟引用、弱引用、虛引用的差別以及使用場景。
強引用置為 null,會不會被回收?
稍微問的深一些的面試官會和記憶體洩漏檢測原理以及垃圾回收糅雜在一起。
-
Java 的泛型,<? super T> 和 <? extends T> 的差別
問到泛型、泛型擦除、通配符相關的東西
- final、finally、finalize 的差別
- 接口、抽象類的差別
2、Android 相關
- 自定義 View
- ViewGroup 繪制順序 (例:自定義 ViewGroup 如何實作 FlowLayout?如何實作 FlowLayout 調換順序)
- 自定義 View 如何實作打桌球效果;
- 自定義 View 如何實作拉弓效果,貝瑟爾曲線原理實作?
事件分發已經不是直接讓你講了,會給你具體的場景,比如 A 嵌套 B ,B 嵌套 C,從 C 中心按下,一下滑出到 A,事件分發的過程,這裡面肯定會有 ACTION_CANCEL 的相關調用時機。
- 解決過的一些性能問題,在項目中的實際運用。
- 性能優化工具 (TraceView、Systrace、調試 GPU 過度繪制 & GPU 呈現模式分析、Hierarchy Viewer、MAT、Memory Monitor & Heap Viewer & Allocation Tracker 等)
- 性能優化 (講講你自己項目中做過的性能優化)
- 網絡:API 優化、流量優化、弱網優化
- 記憶體:OOM 處理、記憶體洩漏、記憶體檢測、分析、Bitmap 優化 LeakCanary 原理,為什麼檢測記憶體洩漏需要兩次?
- 繪制
- 電量:WeakLock 機制、JobScheduler 機制
- APK 瘦身 (APK 瘦身是怎麼做的,隻用 armabi-v7a 沒有什麼問題麼? APK 瘦身這個基本是 100% 被面試問到,可能是我履歷上提到的原因。)
- 記憶體抖動
- 記憶體洩漏
- 卡頓 {如何檢測卡頓,卡頓原理是什麼,怎麼判斷頁面響應卡頓還是邏輯處理造成的卡頓} BlockCanary 的原理 * 性能優化:布局優化、過度渲染處理、ANR 處理、監控、埋點、Crash 上傳。 (10)啟動優化
冷啟動什麼的肯定是基礎,後續應該還有的是懶加載,丢線程池同步處理,需要注意這裡可能會有的坑是,丢線程池如何知道全部完成。
問題:
- 啟動頁白屏及黑屏解決?
- 啟動太慢如何解決?
- 啟動崩潰捕捉?
- Https 請求慢的解決辦法(DNS、攜帶資料、直接通路 IP)
- 緩存自己如何實作(LRUCache 原理)
- 圖形圖像相關:OpenGL ES 管線流程、EGL 的認識、Shader 相關
- SurfaceView、TextureView、GLSurfaceView** 差別及使用場景
- 動畫、內插補點器、估值器 屬性動畫、補間動畫、幀動畫的差別和使用場景
- MVC、MVP、MVVM** 互相間的差別和各種使用場景,如何選擇适合自己的開發架構。
- Handler、ThreadLocal、AsyncTask、IntentService 原理及應用 Handler 機制原理,IdleHandler 什麼時候調用。
- Gradle(Groovy 文法、Gradle 插件開發基礎)
- 熱修複、插件化 (1、談談對 ClassLoader 的了解 2、雙親委托機制的好處 3、自定義 ClassLoader 4. 插件化為什麼會出現,如何代碼加載,資源加載,代理 Hook)
- Activity 生命周期;
- Android 的 4 大啟動模式,注意 onNewIntent() 的調用。
- 講講 Android 的四大元件;
- 元件化架構思路( 1.如何從一個老項目一步步實作元件化,主要問思路,考察架構能力和思考能力。(需要考慮很多,每一步做什麼,順序很重要)2.元件化和子產品化的了解與差別?)
- 系統打包流程
- Android 有哪些存儲資料的方式。
- SharedPrefrence 源碼和問題點;
- sqlite** 相關( 1、sqlite 更新,增加字段的語句 2、資料庫架構對比和源碼分析 3、資料庫優化及資料遷移問題 4、getWritableDatabase 和 getReadableDatabase 的差別)
- ListView 和RecyclerView差別?RecyclerView 有幾層緩存,如何讓兩個 RecyclerView 共用一個緩存? ( 1、RecycleView 如何進行局部重新整理。 2、性能優化。)
- 如何判斷一個 APP 在前台還是背景?
- 如何做應用保活?全家桶原理?
- 混合開發(1. Hybrid 做過嗎?例:Android 通過WebView調用 JS 代碼 例:JS 通過WebView調用 Android 代碼;2.Hybrid 通信原理是什麼,有做研究嗎?3.說說你用過的混合開發技術有哪些?各有什麼優缺點?)
3、Android Framework
- AMS 、PMS
- Activity 啟動流程,App 啟動流程
-
Binder 機制(IPC、AIDL 的使用) (講講 Linux 上的 IPC 通信,Binder 有什麼優勢,Android 上有哪些多程序通信機制?)
項目中遇見了什麼多程序場景?
AIDL 是什麼?解決了什麼問題?
談談對程序共享和線程安全的認知?
什麼是協程?
4、為什麼使用 Parcelable,好處是什麼?
5、 Android 圖像顯示相關流程,Vsync 信号等
4、三方源碼
- Glide :加載、緩存、LRU 算法 (如何自己設計一個大圖加載架構) (LRUCache 原理)
- EventBus
- LeakCanary
-
ARouter
重點:Router 原理,如何實作元件間的通信,元件化平級調用資料的方式。
- 插件化(不同插件化機制原理與流派,優缺點。局限性)
- 熱修複
- RXJava (RxJava 的線程切換原理)
- Retrofit (Retrofit 在 OkHttp 上做了哪些封裝?動态代理和靜态代理的差別,是怎麼實作的)
- OkHttp 和 Volley 的差別。 1、OkHttp 源碼,網絡緩存 2、如果從網絡加載一個 10M 的圖檔,說下注意事項 3、安卓為啥要加簽名機制
5、算法與資料結構
1.單連結清單:反轉、插入、删除
- 雙連結清單:插入、删除
- 手寫常見排序、歸并排序、堆排序
- 二叉樹前序、中序、後序周遊
- 最大 K 問題
- 廣度、深度優先搜尋算法
- 可以去刷一下 LeetCode ,對自己提升也會比較大。
- String 轉 int。 核心算法就三行代碼,不過臨界條件很多,除了判空,還需要注意負數、Integer 的最大最小值邊界等;
- 如何判斷一個單連結清單有環?
- 連結清單翻轉;
- 快排;
- 100 億個單詞,找出出現頻率最高的單詞。要求幾種方案;
- 連結清單每 k 位逆序;
- 鏡像二叉樹;
- 找出一個無序數組中出現超過一半次數的數字;
- 計算二叉樹的最大深度,要求非遞歸算法。
- String 方式計算加法。
6、項目 & HR
- 項目開發中遇到的最大的一個難題和挑戰,你是如何解決的。(95% 會問到)
- 說說你開發最大的優勢點(95% 會問到)
- 你為什麼會離開上家公司
- 你的缺點是什麼?
- 你能給公司帶來什麼效益?
- 你對未來的職業規劃?
總結
提升自己的個人能力才是根本
我上文提到,本文隻針對于國中級Android開發,進階以上的對他們來說可能并無幫助。是以呢,如果你能把自己的能力提升上去,求職方面的困難都會迎刃而解。當然了,想要把自己的開發段位從國中級提升到進階甚至資深,那不是一時半會的事情,也不是我一篇文章就能說清楚的。如果你覺得自己學習效率低,缺乏正确的指導,可以參考下下面分享我多年工作以來收集整理的學習重點,給大家做個參考:
- 熟悉基本的算法和資料結構,擁有良好的程式設計習慣和基本功,能獨立解決大部分開發中遇到的問題。
這條看起來比較抽象,幾乎對于所有的程式員來說,在應聘時都需要滿足這樣的條件,而非僅限于Android,對于不同種類、不同級别的程式員來說,這一條的要求肯定是不同的。那麼對于國中級Android程式員來說,這一條看的就是你的基礎了。
算法:也許你在工作中真的用不到算法,但面試官如果問你什麼是快速排序,你完全說不上來,場面也是很尴尬的。算法方面懂得不用太多,但是最基本的冒泡、快排、二分等,要懂得實作,最好能手寫出來,當然不要求手寫的完全無錯誤,但是思路要是對的才行。
資料結構:這個比算法更常用一些,畢竟大部分Android程式員工作裡用不到算法,但絕對要用一些資料結構的。像數組(ArrayList)、連結清單(LinkedList)、Hash(HashMap)、棧(Stack)等這都是很常用的,十分推薦大家看看Java源碼,看看這些常用的資料結構是如何實作的。
程式設計習慣和基本功:需要看你的代碼邏輯是否清晰,注釋是否到位等等。其實這裡有一個很簡單的辦法來判斷程式設計習慣,就是一眼看上去,你寫的代碼有沒有一種“優雅”的感覺。例如一些換行和空格與縮進等,能否讓人看上去賞心悅目。而注釋同樣重要,否則幾天後這段代碼連你自己都看不懂,更别說換人接手了。
- 熟悉Java語言,最好熟悉Kotlin語言
相信這一點大家都能了解,你作為一個Android開發,不熟悉Java能行嗎?當然具體要熟悉到什麼程度呢?
倒是讓我想起來一個梗:面試的時候千萬不要寫自己“精通”XX語言,一旦寫了精通,不管你精通的是什麼,接下來面試官會在這個方面瘋狂的探究細節,往死裡怼你的。哈哈,現實中還真有這樣的面試官,而且為數不少,是以這也成了約定俗成的規矩了。
好了,言歸正傳,作為一個Android開發,大緻需要哪些Java基礎呢?我列舉一下,可能一時想的不太全面,姑且看之吧,今後有空可以詳細的寫一下。
基本的資料類型及對應的封裝類:byte(Byte)、short(Short)、int(Integer)、long(Long)、float(Float)、double(Double)、char(Character)。
運算符:算術運算符(+、-、*、/、%、++、--)、關系運算符(>、<、==、!=、>=、<=)、位運算符(<<、>>、&、|、^、~、>>>)、邏輯運算符(&&、||、!)、指派運算符(=,以及一大串的先運算後指派的運算符如+=)、instanceof運算符等。
循環:for循環、foreach循環、do-while循環、while循環。
分支:switch、if-else。
面向對象:類、對象、構造方法、繼承、多态、重載、抽象、接口等。
設計模式:最常用的有單例模式、工廠模式、觀察者模式等。
異常處理:各種異常類型,try-catch-finally。
多線程:Thread、Runnable,synchronized關鍵字。
IO:File、FileInput、FileOutput、FileInputStream、FileOutputStream、各個Writer和Reader類等。
常用類:ArrayList、HashMap、Calendar、Date等。
至于Kotlin語言嘛,比Java簡潔不少,寫起來十分帶感,可以把它當成一個更好用的加強版Java。現在Google推動Kotlin的力度很大,雖然學會Kotlin并不能說是絕對必須的,但絕對是應聘時的一個重大加分項,一些好一點職位甚至會把它當成必備技能。
- 在Android方面應該掌握的基礎
作為一個Android開發,這方面可謂是必須掌握的,也是個十分寬泛的話題了,還是簡單來說一下吧:
了解一個Android App工程的組成,了解每個目錄都代表了什麼(這是基礎中的基礎,你去面試Android開發,不可能連這個都不懂的)。
Activity:了解基本的生命周期,以及每個周期到底對使用者和開發者意味着什麼。如果能從源碼級别了解Activity那就更好了。熟悉頁面之間的跳轉,資料傳遞,要是還能帶上動畫那就很出彩了。
Service:了解Service的生命周期和啟動流程,知道什麼情況下使用Service,跟Activity之間的資料互動。
ContentProvider:知道ContentProvider的原理,知道簡單的使用。
BroadcastReceiver:知道如何發廣播和接收廣播,了解動态與靜态注冊廣播的差別,懂得使用本地廣播。
Fragment:熟悉Fragment的生命周期,與父Activity的關系,彼此的資料傳遞。
Layout:LinearLayout、FrameLayout、RelativeLayout和ConstraintLayout,知道它們的差別,清楚适合它們的應用場景。在完成符合産品原型與UI設計的布局同時,還要做到螢幕适配。
Wigdet:TextView、ImageView、EditText、ScrollView、ListView、RecyclerView、Button等,最好能夠做到自己實作一個高性能的View。
第三方SDK:要熟悉一些幾乎是“必備”的第三方SDK的內建和使用,比如支付寶和微信支付,極光或友盟的推送,友盟、騰訊等的統計與BUG分析,百度或高德地圖,第三方分享(微信、QQ、微網誌等),IM即時通訊(如環信、融雲等)。其中有的SDK不僅要會使用,還要做到一些自定義。
開源庫:RxJava(非常重要,能讓我們在開發時實作響應式程式設計,避免無窮無盡的縮進,十分推薦深入研究源碼。我一看到履歷上寫着熟悉使用AsyncTask實作異步的就很煩……)、Retrofit+OkHttp(非常重要,現在你如果還在用Async-Http-Client或者Volley都根本不好意思跟人說話,盡管後兩者也能實作功能需求)、ButterKnife、圖檔加載(Glide、Picasso、Fresco等總得熟悉一種)、資料庫(GreenDao、Realm、Ormlite等,自己寫SQLite還是麻煩了點)、Json解析(Gson、FastJson、Jackson、LoganSquare等)、性能分析(LeakCanary、BlockCanary等)。
架構:MVC、MVP、MVVM、Android Flux等,不管你選擇哪個,基本要求是寫出來的App架構清晰、别人了解起來容易。
工具:Android Studio這個IDE是不用多說了,不僅能開發,而且還進行性能分析等(如果你還在用Eclipse,那就當我啥都沒說吧……)。最常見的團隊代碼管理Git也要熟練使用(什麼?你們公司用的還是SVN?)。
- 其他方面
這裡指的不是你是技術了,而是看你個人的綜合素質了。
比如,作為一個Android開發者,你是否會留意每個Android版本的變動(尤其是對我們開發有影響的)?
你的自主學習能力如何?一般來說,招你進來,是希望你能繼續進步的,如果一直原地踏步,即使短時間不被淘汰,以後又如何适應職場的競争呢?Android發展速度其實已經不像幾年前那麼迅猛了(任何一個生态在比較穩定後都是這樣),但每年還是有不少的新東西,長期不進步,肯定會被淘汰。
你的溝通交流能力怎麼樣?入職一家新公司,進入一個新部門、新團隊,能否很快的融入新環境,很快的投入到工作中?而平時工作,也要跟許多同僚打交道,如果溝通能力太差,那會讓所有人都不舒服。是的,程式員的核心競争力在于技術,但是僅有技術是不夠的,相信大家懂這個道理。