首頁>科技>

前言

不得不說,前兩年的移動開發確實很紅,可以說隨便能鼓搗出來點東西都很容易找到工作。而現在明顯降溫了,對人才的要求也越來越苛刻,所以跟前兩年比需求確實少了很多。但是安卓不僅僅侷限於手機,智慧家居車載系統電視機頂盒智慧機器人的觸控板設定大部分都是搭載的安卓系統,所以市場的需求還是很大的。

本文希望達到的目的是為職場新人和畢業生提供一個面試經驗的分享,使讀者在找工作時有一個參考少走彎路,通過本文的閱讀將收穫到:

面試前的準備,簡歷編寫規範和重點;面試經歷,大廠和小廠的區別和考察點;安卓面試常問的知識點解析;目前主流框架的使用,如何快速上手專案;附歷年大廠面試題總結。

概述

對於我們程式設計師而言,面試就是將自己所學的技術與面試官表達出來。以前上學準備找工作的時候,發現最先找到工作的不是技術最好的而是善於溝通活躍度高的人,而我聽的最多的抱怨是 “為什麼我明明知道這個東西,面試的時候卻不知從何說起”。

本文會從我的自身經歷出發談一談面試前如何做好充分準備,怎麼流暢的表達自己的技術,以及進入專案時如何從一開始的手足無措、盲目下手到後來的淡定從容。

面試前準備

簡歷編寫

對於任何階段的面試者來說擁有一份精緻的簡歷是很重要的,所謂精緻就是要突出重點,特別對於技術類的簡歷來說廢話越少越好。好的簡歷要有辨識度,記得以前聽 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 儲存資料

首先說明 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”

它們主要有如下不同:

如何決定所屬 task

“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 傳送給該例項,而不傳送給新的例項。

是否允許其它 activity 存在於本 task 內

“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 會通過依賴關係並且生成易懂易分析的程式碼。以前通過手寫的大量模板程式碼中的物件引用將會由它給你建立並傳遞到相應物件中。因此你可以更多的關注模組中構建的內容而不是模組中的物件例項的建立順序。

讓單元測試和整合測試更加方便

因為依賴關係已經為我們獨立出來,所以我們可以輕鬆的抽取出不同的模組進行測試。依賴的注入和配置獨立於元件之外。因為物件是在一個獨立、不耦合的地方初始化,所以當注入抽象方法的時候,我們只需要修改物件的實現方法,而不用大改程式碼庫。依賴可以注入到一個元件中:我們可以注入這些依賴的模擬實現,這樣使得測試更加簡單。

作用域例項(Scoped instances)

我們不僅可以輕鬆的管理全域性例項物件,也可以使用 Dagger2 中的 scope 定義不同的作用域。(比如根據 user session、activity 的生命週期)

什麼是 Retrofit

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

動態載入

類載入器

OSGI

Https 請求慢的解決辦法,DNS,攜帶資料,直接訪問 IP

GC 回收策略

畫出 Android 的大體架構圖

大體說清一個應用程式安裝到手機上時發生了什麼;

對 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開發面試專題資料,高階進階架構資料幫助大家學習提升進階,也節省大家在網上搜索資料的時間來學習,也可以分享給身邊好友一起學習

如果你有需要的話,可以點贊+轉發,關注我,然後私信我【學習】我發給你

最新評論
  • 整治雙十一購物亂象,國家再次出手!該跟這些套路說再見了
  • 中國頂級黑客在國際上是什麼樣的水平?