不得不說,前兩年的移動開發確實很火,能夠說隨便能鼓搗出來點東西都很容易找到工做。而如今明顯降溫了,對人才的要求也愈來愈苛刻,因此跟前兩年比需求確實少了不少。可是安卓不只僅侷限於手機,智能家居車載系統電視機頂盒智能機器人的觸摸板設置大部分都是搭載的安卓系統,因此市場的需求仍是很大的。react
本文但願達到的目的是爲職場新人和畢業生提供一個面試經驗的分享,使讀者在找工做時有一個參考少走彎路,經過本文的閱讀將收穫到:android
對於咱們程序員而言,面試就是將本身所學的技術與面試官表達出來。之前上學準備找工做的時候,發現最早找到工做的不是技術最好的而是善於溝通活躍度高的人,而我聽的最多的抱怨是 「爲何我明明知道這個東西,面試的時候殊不知從何提及」。程序員
本文會從個人自身經歷出發談一談面試前如何作好充分準備,怎麼流暢的表達本身的技術,以及進入項目時如何從一開始的手足無措、盲目下手到後來的淡定從容。面試
簡歷編寫算法
對於任何階段的面試者來講擁有一份精緻的簡歷是很重要的,所謂精緻就是要突出重點,特別對於技術類的簡從來說廢話越少越好。好的簡歷要有辨識度,記得之前聽 HR 聊天時說:「明明沒啥東西寫了兩三頁,看到後面才知道他要幹嗎,簡直浪費紙」大部分人寫簡歷都會用網上的模板,固然用模板寫會節省很大的人力並且格式也更好看。然而模板上面有不少套話,數據庫
這段自我評價估計不少人都會感到很熟悉,甚至一部分人的簡歷上面還有,由於每一個人均可以這樣寫。想想這種評價 HR 天天看了多少遍,再看下面這張簡歷案例,在評價欄羅列出本身的技術點,突出重點一目瞭然。設計模式
剛畢業出來找工做的同窗來講,沒有上圖有那麼多幹貨能夠寫,怎麼才能突出重點呢,教一個小技巧,你們能夠瀏覽幾十家不一樣類型公司的任職要求,你會發現有兩到三條几乎是相同的,那麼這兩到三條技術點就是你必需要掌握的了,並且技術評價裏面必定要寫出來。緩存
簡歷編寫要適度不要給本身挖坑,掌握不能寫成精通了解不能寫成掌握,精通在瞭解怎麼用的同時還要了解它的底層實現,掌握的話就要知道它的用法以及出現問題怎麼解決。瞭解的話就要知道這個技術點能夠處理什麼問題,瞭解一些 API 怎麼調用。性能優化
技能儲備微信
Java 基礎知識方面須要掌握的有:面向對象的理解、基本類型與引用類型、構造方法、經常使用類(內部類、匿名類、抽象類)、三大特性(封裝、繼承、多態)、重寫與重載、接口與接口的實現等等。這些問題面試官會在掌握的層面上去問你,主要是考察你的基礎知識是否紮實,畢竟安卓是用 Java 編寫的。
Android 方面須要掌握的有:四大組件的簡單使用、activity 的生命週期、fragment 的綁定、activity 和 fragment 之間的傳值、 recyclerview 實現列表九宮格瀑布流式佈局的實現、viewHolder 的複用問題、數據存儲的幾種方式的特色、經常使用框架 Glide、Retrofit、eventBus、butterknife 的使用。
Java 基礎知識須要掌握的有:對於兩到三年的安卓程序員來講,Java 不只僅是停留在一些基礎知識的使用上了,而是在用的同時要有本身的理解。好比說封裝,面試官不會問你什麼是封裝,而是會問你封裝過公司的哪些代碼/功能,你是如何封裝的。這個時候考察的就是你是會寫代碼仍是隻會模仿代碼,若是沒有本身在項目中封裝過代碼的話能夠去閱讀下網上一些優秀的框架的源碼學習一下別人是怎麼封裝的。
固然不只僅是封裝還有不少知識點都要按照這個要求去掌握,好比:Java 泛型、反射、集合框架、接口與抽象類、設計模式等等。掌握這些除了看視頻學習還能夠閱讀一些優秀的源碼。不懂的地方再查一查博客,理解透了後必定要在本身項目上運用,這樣學習才能印象深入面試官問到也能有列可舉。
Android 方面須要掌握的有:APP 啓動原理,想要詳細瞭解的能夠看個人另外一篇 chat (APP 啓動原理及啓動優化詳解 )、圖片壓縮與性能優化、自定義 view 、事件分發流程、屏幕適配、組件化和插件化、Glide 的緩存與複用、OkHttp 的責任鏈與鏈接池、序列化與反序列化、分析一個你最熟練框架的源碼等等。能夠看到,對於兩到三年的程序員來講不只掌握的知識點更多,並且還須要對原理有必定的瞭解。
大廠面試經歷
本人剛出來找工做的時候面試了不少家,那時候是移動開發的爆發時期,其中有萬能鑰匙等中大型公司也有一些剛創業的小公司,固然大廠最終面試失敗了。記得去萬能鑰匙面試的時候,去面試的人特別的多,須要在大廳等待,一批一批的去面試,先是羣面,瞭解基本狀況事後,就是單獨面談等待面試,總共三輪面試,面試官會通知面試結果出來的時間。
面試官提到的問題有:爲何從上一家離職、如何看待咱們公司、本身之後的職業規劃是什麼、技術方面問了 Java 的內存回收機制,內存溢出和內存泄漏、如何避免 OOM 異常、什麼是 AIDL,AIDL 怎麼使用、 android 線程間通訊有那幾種方式、Glide 三級緩存怎麼實現的。
大小廠考察點的區別
流程比較多,通常會有三面以上,首先會有一套面試題等着你,固然不是全部公司都有面試題,只不過大廠有面試題的機率會高些,其次技術主管面試,而後技術經理面試,人事會跟你介紹公司的發展業務公司福利工做時間等等。大廠的開發通常是分模塊開發,每一個人單獨負責某一個模塊,因此要求你要有本身的優點點,好比你會寫自定義組件,視頻模塊,對 NDK 深有研究等等。
流程少,有可能一面過了就叫你來上班了。小公司面試必定要問清楚工資何時發,月初發說明公司資金充足,月中旬發是正常的,若是月末才發的話公司資金緊張極可能出現財務危機。還有五險一金有沒有,有的話試用期有沒有,目前還有一部分公司沒有五險一金的,並且大部分公司試用期不交五險一金。關於五險一金的重要性你們能夠去百度搜一搜,限購令出來後這個更加劇要了。
關於技術方面的區別就是,小公司通常都是一我的開發,要求你知道整個項目的開發流程,可是對於技術深度要求不高(僅僅對於初級程序員來講,高級架構師就另說了)。面試以前多準備些項目去演示,有些人說懂技術的都不看做品的,可是對於小公司就不一樣了,有可能面試你的是產品經理、後臺人員等等,對安卓瞭解的也不是很深,這時候有幾個好的做品演示必定會給你的面試加很多分。
如下五個問題本人面試的時候都被問到過,也做爲面試官考察過別人,算是比較有表明性的題目。
Activity 的生命週期
這個問題的關鍵是理解,這道面試題還有其餘的問法,好比:問onStart()、與 onResume() 有什麼區別?什麼狀況下 Activity 走了onCreat(),而不走 onStart()?
請介紹下 Android 的數據存儲方式。
使用 SharedPreferences 存儲數據;文件存儲數據;SQLite 數據庫存儲數據;使用 ContentProvider 存儲數據;網絡存儲數據。
Preference,File, DataBase 這三種方式分別對應的目錄是 /data/data/Package Name/Shared_Pref, /data/data/Package Name/files, /data/data/Package Name/database 。
首先說明 SharedPreferences 存儲方式,它是 Android 提供的用來存儲一些簡單配置信息的一種機制,例如:登陸用戶的用戶名與密碼。其採用了 Map 數據結構來存儲數據,以鍵值的方式存儲,能夠簡單的讀取與寫入,具體實例以下:
void ReadSharedPreferences(){ String strName,strPassword; SharedPreferences user = getSharedPreferences(「user_info」,0); strName = user.getString(「NAME」,」」); strPassword = user getString(「PASSWORD」,」」); } void WriteSharedPreferences(String strName,String strPassword){ SharedPreferences user = getSharedPreferences(「user_info」,0); uer.edit(); user.putString(「NAME」, strName); user.putString(「PASSWORD」 ,strPassword); user.commit(); }
數據讀取與寫入的方法都很是簡單,只是在寫入的時候有些區別:先調用 edit() 使其處於編輯狀態,而後才能修改數據,最後使用 commit() 提交修改的數據。實際上 SharedPreferences 是採用了 XML 格式將數據存儲到設備中,在 DDMS 中的 File Explorer 中的 /data/data/<package name>/shares_prefs 下。使用 SharedPreferences 是有些限制的:只能在同一個包內使用,不能在不一樣的包之間使用。
文件存儲方式是一種較經常使用的方法,在 Android 中讀取/寫入文件的方法,與 Java 中實現 I/O 的程序是徹底同樣的,提供了 openFileInput() 和openFileOutput() 方法來讀取設備上的文件。具體實例以下:
String fn = 「moandroid.log」; FileInputStream fis = openFileInput(fn); FileOutputStream fos = openFileOutput(fn,Context.MODE_PRIVATE);
網絡存儲方式,須要與 Android 網絡數據包打交道,關於 Android 網絡數據包的詳細說明,請閱讀 Android SDK 引用了 Java SDK 的哪些package?。
activity的啓動模式有哪些?是什麼含義?
在 Android 裏,有 4 種 activity 的啓動模式,分別爲:
「standard」 (默認)
「singleTop」
「singleTask」
「singleInstance」
它們主要有以下不一樣:
「standard」 和 」singleTop」 的 activity 的目標 task,和收到的 Intent 的發送者在同一個 task 內,除非 intent 包括參數 FLAG_ACTIVITY_NEW_TASK。
若是提供了 FLAG_ACTIVITY_NEW_TASK 參數,會啓動到別的 task 裏。
「singleTask」 和 」singleInstance」 老是把 activity 做爲一個 task 的根元素,他們不會被啓動到一個其餘 task 裏。
「standard」 和 」singleTop」 能夠被實例化屢次,而且存在於不一樣的 task 中,且一個 task 能夠包括一個 activity 的多個實例。
「singleTask」 和 」singleInstance」 則限制只生成一個實例,而且是 task 的根元素。 singleTop 要求若是建立 intent 的時候棧頂已經有要建立的 Activity的實例,則將 intent 發送給該實例,而不發送給新的實例。
「singleInstance」 獨佔一個 task,其它 activity 不能存在那個 task 裏;若是它啓動了一個新的 activity,無論新的 activity 的 launch mode 如何,新的activity 都將會到別的 task 裏運行(如同加了 FLAG_ACTIVITY_NEW_TASK參數)。
而另外三種模式,則能夠和其它 activity 共存。
「standard」 對於沒一個啓動 Intent 都會生成一個 activity 的新實例。
「singleTop」 的 activity 若是在 task 的棧頂的話,則不生成新的該 activity 的實例,直接使用棧頂的實例,不然,生成該 activity 的實例。
好比如今 task 棧元素爲 A-B-C-D(D在棧頂),這時候給 D 發一個啓動 intent,若是 D 是 「standard」 的,則生成 D 的一個新實例,棧變爲 A-B-C-D-D。
若是 D 是 singleTop 的話,則不會生產 D 的新實例,棧狀態仍爲 A-B-C-D。
若是這時候給 B 發 Intent 的話,無論 B 的 launchmode 是 」standard」 仍是 「singleTop」 ,都會生成 B 的新實例,棧狀態變爲 A-B-C-D-B。
「singleInstance」 是其所在棧的惟一 activity,它會每次都被重用。
「singleTask」 若是在棧頂,則接受 intent,不然,該 intent 會被丟棄,可是該 task 仍會回到前臺。
當已經存在的 activity 實例處理新的 intent 時候,會調用 onNewIntent() 方法 若是收到 intent 生成一個 activity 實例,那麼用戶能夠經過 back 鍵回到上一個狀態;若是是已經存在的一個 activity 來處理這個 intent 的話,用戶不能經過按 back 鍵返回到這以前的狀態。
什麼是 ANR 如何避免它?
ANR:Application Not Responding。在 Android 中,活動管理器和窗口管理器這兩個系統服務負責監視應用程序的響應,當用戶操做的在 5s 內應用程序沒能作出反應,BroadcastReceiver 在 10 秒內沒有執行完畢,就會出現應用程序無響應對話框,這既是 ANR。
避免方法:Activity 應該在它的關鍵生命週期方法(如 onCreate() 和onResume())裏儘量少的去作建立操做。潛在的耗時操做,例如網絡或數據庫操做,或者高耗時的計算如改變位圖尺寸,應該在子線程裏(或者異步方式)來完成。主線程應該爲子線程提供一個 Handler,以便完成時可以提交給主線程。
註冊廣播有幾種方式,這些方式有何優缺點?請談談 Android 引入廣播機制的用意。
首先寫一個類要繼承 BroadcastReceiver
第一種:在清單文件中聲明,添加
第二種使用代碼進行註冊如
兩種註冊類型的區別是:
搭建項目的主流框架集
Dagger2+RxJava+Retrofit+MVP 是本人目前用的框架集,目前使用的很普遍, 四個相結合,組成項目的優美總體架構。 須要導入的包
> dependencies { // 網絡請求 compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:adapter-rxJava:2.0.1' compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4' compile 'com.squareup.retrofit2:converter-scalars:2.0.0-beta4' compile 'com.squareup.okhttp3:okhttp:3.2.0' // 註解 compile 'com.google.dagger:dagger:2.0.2' apt 'com.google.dagger:dagger-compiler:2.0.2' provided 'org.glassfish:Javax.annotation:10.0-b28' compile 'com.jakewharton:butterknife:7.0.1' // Rx compile 'io.reactivex:rxandroid:1.1.0' compile 'io.reactivex:rxJava:1.1.5' }
下面是 MVP 的架構圖
如上圖所示
View 與 Model 並不直接交互,而是使用 Presenter 做爲 View 與 Model 之間的橋樑。
其中 Presenter 中同時持有 view 層以及 Model 層的 Interface 的引用,View 層持有 Presenter 層 Interface 的引用。當 View 層某個界面須要展現某些數據的時候,首先會調用 Presenter 層的某個接口,而後 Presenter 層會調用 Model 層請求數據。
當 Model 層數據加載成功以後會調用 Presenter 層的回調方法通知 Presenter 層數據加載完畢。
最後 Presenter 層再調用 View 層的接口將加載後的數據展現給用戶。這就是 MVP 模式的整個核心過程,若是你是面試初級安卓開發,面試官應該只會讓你闡述下整個調用過程,只要你能流暢的說完整個過程應該差很少了。
Dagger2 的流程圖
什麼是 Dagger2
Dagger2 是一個依賴注入框架,butterknife 也是一個依賴注入框架。不過 butterknife,最多叫奶油刀,Dagger2 被叫作利器啊,他的主要做用,就是對象的管理,其目的是爲了下降程序耦合。
Dagger2 的優勢
和 ButterKnife 庫定義了view,事件處理以及資源的引用同樣,Dagger2 提供全局對象引用的簡易訪問方式。聲明瞭單例的實例均可以使用 @inject 進行訪問。好比下面的 MyTwitterApiClient 和SharedPreferences 的實例:
> public class MainActivity extends Activity { @Inject MyTwitterApiClient mTwitterApiClient; @Inject SharedPreferences sharedPreferences; public void onCreate(Bundle savedInstance) { // assign singleton instances to fields InjectorClass.inject(this); }
Dagger2 會經過依賴關係而且生成易懂易分析的代碼。之前經過手寫的大量模板代碼中的對象引用將會由它給你建立並傳遞到相應對象中。所以你能夠更多的關注模塊中構建的內容而不是模塊中的對象實例的建立順序。
由於依賴關係已經爲咱們獨立出來,因此咱們能夠輕鬆的抽取出不一樣的模塊進行測試。依賴的注入和配置獨立於組件以外。由於對象是在一個獨立、不耦合的地方初始化,因此當注入抽象方法的時候,咱們只須要修改對象的實現方法,而不用大改代碼庫。依賴能夠注入到一個組件中:咱們能夠注入這些依賴的模擬實現,這樣使得測試更加簡單。
咱們不只能夠輕鬆的管理全局實例對象,也可使用 Dagger2 中的 scope 定義不一樣的做用域。(好比根據 user session、activity 的生命週期)
Retrofit 是 Square 開發的一個 Android 和 Java 的 REST 客戶端庫。這個庫很是簡單而且具備不少特性,相比其餘的網絡庫,更容易讓初學者快速掌握。
建立 Retrofit 實例時須要經過 Retrofit.Builder,並調用 baseUrl 方法設置 URL。
接口定義
以獲取時間列表爲例
> public interface TimeService { > @GET("getTimes?") Call< ResponseBody > getTimes (@Query("month") String month); }
注意,這裏是 interface 不是 class,因此咱們是沒法直接調用該方法,咱們須要用 Retrofit 建立一個 TimeService 的代理對象。
TimeService timeService= createRetrofit().create(TimeService .class);
接口調用
> Call<ResponseBody> mService= timeService.getTimes ("1"); mService.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { try { Log(response.body().string()); } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { t.printStackTrace(); } });
如何快速理解項目進行二次開發
當咱們進入一個新公司工做,有可能接手的不是一個新項目而是維護別人開發的項目,面對龐大的項目不知從何下手。在這裏我要告訴你們的是,拿到項目的時候不要盲目的進行開發而是閱讀項目源碼。閱讀源碼首先瀏覽項目結構,
經過這張結構圖能夠了解項目用的是 MVP 架構,有兩個 lib 一個和 service 有關 一個和圖片處理有關。而後再閱讀 build.gradle 文件,裏面有項目中用到的第三方庫的引用地址,知道項目中用到了哪些技術,若是有不熟悉的第三方庫就能夠根據這個地址去查找資源熟悉調用方式項目中用到的模塊,往後逐漸研究庫的源碼以及實現原理。等這些瞭解的差很少了,再看一看需求文檔和設計圖,對着需求走一遍流程,主要記錄 activity 之間的跳轉,能夠畫一張類之間跳轉的結構圖,這樣整個跳轉的邏輯會更清晰。
還有兩個值得閱讀的是:項目中的工具類和封裝的組件。相信很多人遇到過,在網上找了好久的一個處理數據的方法,過了數日發現項目的工具類中有直接就能夠拿來用。封裝的組件也和工具相似能夠直接拿來用的,在後面的開發也提倡你們將項目組件化。
騰訊
synchronize 用法
volatile 用法
動態權限適配方案,權限組的概念
網絡請求緩存處理,okhttp 如何處理網絡緩存的
圖片加載庫相關,bitmap 如何處理大圖,如一張 30M 的大圖,如何預防 OOM
進程保活
listview 圖片加載錯亂的原理和解決方案
https 相關,如何驗證證書的合法性,https 中哪裏用了對稱加密,哪裏用了非對稱加密,對加密算法(如 RSA)等是否有了解
阿里巴巴
LRUCache 原理
圖片加載原理
模塊化實現(好處,緣由)
視頻加密傳輸
統計啓動時長,標準
如何保持應用的穩定性
ThreadLocal 原理
談談 classloader
動態佈局
熱修復、插件化
HashMap 源碼, SpareArray 原理
性能優化,怎麼保證應用啓動不卡頓
SP 是進程同步的嗎?有什麼方法作到同步
介紹下 SurfView
HashMap 實現原理,ConcurrentHashMap 的實現原理
BroadcastReceiver,LocalBroadcastReceiver 區別
Bundle 機制
Handler 機制
android 事件傳遞機制
線程間 操做 List
App啓動流程,從點擊桌面開始
動態加載
類加載器
OSGI
Https 請求慢的解決辦法,DNS,攜帶數據,直接訪問 IP
GC 回收策略
畫出 Android 的大致架構圖
描述清點擊 Android Studio 的 build 按鈕後發生了什麼
大致說清一個應用程序安裝到手機上時發生了什麼;
對 Dalvik、ART 虛擬機有基本的瞭解;
Android 上的 Inter-Process-Communication 跨進程通訊時如何工做的;
App 是如何沙箱化,爲何要這麼作;
權限管理系統(底層的權限是如何進行 grant 的);
進程和 Application 的生命週期;
系統啓動流程 Zygote 進程 –> SystemServer 進程 –> 各類系統服務 –> 應用進程
美團
線程掛起,休眠,釋放資源相關,喚醒,線程同步,數據傳遞,問了不少線程的問題,問了 20 分鐘大概
static synchronized 方法的多線程訪問和做用,同一個類裏面兩個 synchronized 方法,兩個線程同時訪問的問題
內部類和靜態內部類和匿名內部類,以及項目中的應用
泛型是什麼以及在項目中的應用
handler 發消息給子線程,looper 怎麼啓動
down、move、up 事件的傳遞
activity 棧
封裝 view 的時候怎麼知道 view 的大小
intent-filter
arraylist 和 linkedlist 的區別,以及應用場景
怎麼啓動 service,service 和 activity 怎麼進行數據交互
下拉狀態欄是否是影響 activity 的生命週期,若是在 onStop 的時候作了網絡請求,onResume 的時候怎麼恢復
view 渲染
對於基礎知識考察的比較多,注重原理,要求面試者在學習技術的時候加深理解。不一樣的公司在業務側重點方面有所不一樣,但整體須要掌握的技能有:高級 UI、性能優化、移動架構等方面。
感謝你們能耐着性子,看完我囉哩囉嗦的文章。
我願與各位堅守在Android開發崗位的同胞們互相交流學習,共同進步!
在這裏我也分享一份本身收錄整理的Android學習PDF+架構視頻+面試文檔+源碼筆記,還有高級架構技術進階腦圖、Android開發面試專題資料,高級進階架構資料幫助你們學習提高進階,也節省你們在網上搜索資料的時間來學習,也能夠分享給身邊好友一塊兒學習
若是你有須要的話,能夠點贊,關注我,而後關注微信公衆號【Android開發之家】免費領取