敲黑板!送分題呀,同學們,10道面試阿里Android崗面試官必問的面試題,來源于CSDN及牛客網等平臺上的一些去阿里面試的同學的高贊真實面經分享,將其高頻面試題整合下來,并在我大廠架構師朋友的幫助下,做出了對應的參考回答及決議,廢話不多說,大家自己來試試,不看回答參考的話,你會怎么回答?
1. 橫豎屏切換的Activity生命周期變化?
參考回答:
不設定Activity的android:configChanges時,切屏會銷毀當前Activity,然后重新加載呼叫各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次;onPause()→onStop()→onDestory()→onCreate()→onStart()→onResume()設定Activity的android:configChanges=“orientation”,經過機型測驗
- 在Android5.1 即API 23級別下,切屏還是會重新呼叫各個生命周期,切橫、豎屏時只會執行一次 - 在Android9 即API 28級別下,切屏不會重新呼叫各個生命周期,只會執行onConfigurationChanged方法后經官方查正,原話如下:
- 如果您的應用面向Android 3.2即API 級別 13或更高級別(按照 minSdkVersion 和 targetSdkVersion 屬性所宣告的級別),則還應宣告 “screenSize” 配置,因為當設備在橫向與縱向之間切換時, 該配置也會發生變化,即便是在 Android 3.2 或更高版本的設備上運行,此配置變更也不會重新啟動 Activity
- 設定Activity的android:configChanges="orientation|keyboardHidden|screenSize"時,機型測驗通過,切屏不會重新呼叫各個生命周期,只會執行onConfigurationChanged方法;
2. Fragment中add與replace的區別(Fragment重疊)
參考回答:
- add不會重新初始化fragment,replace每次都會,所以如果在fragment生命周期內獲取獲取資料,使用replace會重復獲取;
- 添加相同的fragment時,replace不會有任何變化,add會報IllegalStateException例外;
- replace先remove掉相同id的所有fragment,然后在add當前的這個fragment,而add是覆寫前一個fragment,所以如果使用add一般會伴隨hide()和show(),避免布局重疊;
- 使用add,如果應用放在后臺,或以其他方式被系統銷毀,再打開時,hide()中參考的fragment會銷毀,所以依然會出現布局重疊bug,可以使用replace或使用add時,添加一個tag引數;

3. 如何保證Service不被殺死 ?
參考回答:
3.1 onStartCommand方式中,回傳START_STICKY或則START_REDELIVER_INTENT
- START_STICKY: 如果回傳START_STICKY,表示Service運行的行程被Android系統強制殺掉之后,Android系統會將該Service依然設定為started狀態(即運行狀態),但是不再保存onStartCommand方法傳入的intent物件
- START_NOT_STICKY: 如果回傳START_NOT_STICKY,表示當Service運行的行程被Android系統強制殺掉之后,不會重新創建該Service
- START_REDELIVER_INTENT: 如果回傳START_REDELIVER_INTENT,其回傳情況與START_STICKY類似,但不同的是系統會保留最后一次傳入onStartCommand方法中的Intent再次保留下來并再次傳入到重新創建后的Service的onStartCommand方法中
3.2 提高Service的優先級 在AndroidManifest.xml檔案中對于intent-filter可以通過android:priority ="1000"這個屬性設定最高優先級,1000是最高值,如果數字越小則優先級越低,同時適用于廣播;
3.3 在onDestroy方法里重啟Service 當service走到onDestroy()時,發送一個自定義廣播,當收到廣播時,重新啟動service;
3.4 提升Service行程的優先級 行程優先級由高到低:前臺行程 一 可視行程 一 服務行程 一 后臺行程 一空行程 可以使用startForeground將service放到前臺狀態,這樣低記憶體時,被殺死的概率會低一些;
3.5 系統廣播監聽Service狀態;
3.6 將APK安裝到/system/app,變身為系統級應用;
注意:以上機制都不能百分百保證Service不被殺死,除非做到系統白名單,與系統同生共死,
4. 描述一下Android資料持久存盤方式
參考回答: Android平臺實作資料持久存盤的常見幾種方式:
- SharedPreferences存盤:一種輕型的資料存盤方式,本質是基于XML檔案存盤的key-value鍵值對資料,通常用來存盤一些簡單的配置資訊(如應用程式的各種配置資訊);
- SQLite資料庫存盤:一種輕量級嵌入式資料庫引擎,它的運算速度非常快,占用資源很少,常用來存盤大量復雜的關系資料;
- ContentProvider:四大組件之一,用于資料的存盤和共享,不僅可以讓不同應用程式之間進行資料共享,還可以選擇只對哪一部分資料進行共享,可保證程式中的隱私資料不會有泄漏風險;
- File檔案存盤:寫入和讀取檔案的方法和 Java中實作I/O的程式一樣;網路存盤:主要在遠程的服務器中存盤相關資料,用戶操作的相關資料可以同步到服務器上;
5. Android中IPC方式、各種方式優缺點,為什么選擇Binder?
參考回答:

與Linux上傳統的IPC機制,比如System V,Socket相比,Binder好在哪呢?
- 傳輸效率高、可操作性強
傳輸效率主要影響因素是記憶體拷貝的次數,拷貝次數越少,傳輸速率越高,從Android行程架構角度分析:對于訊息佇列、Socket和管道來說,資料先從發送方的快取區拷貝到內核開辟的快取區中,再從內核快取區拷貝到
接收方的快取區,一共兩次拷貝,如圖:

而對于Binder來說,資料從發送方的快取區拷貝到內核的快取區,而接收方的快取區與內核的快取區是映射到同
一塊物理地址的,節省了一次資料拷貝的程序,如圖:

由于共享記憶體操作復雜,綜合來看,Binder的傳輸效率是最好的, - 實作C/S架構方便: Linux的眾IPC方式除了Socket以外都不是基于C/S架構,而Socket主要用于網路間的通信且傳輸效率較低,Binder基于C/S架構 ,Server端與Client端相對獨立,穩定性較好,
- 安全性高: 傳統Linux IPC的接收方無法獲得對方行程可靠的UID/PID,從而無法鑒別對方身份;而Binder機制為每個行程分配了UID/PID且在Binder通信時會根據UID/PID進行有效性檢測,
6. Bundle傳遞物件為什么需要序列化?Serialzable和Parcelable的區別?
參考回答:
- 因為bundle傳遞資料時只支持基本資料型別,所以在傳遞物件時需要序列化轉換成可存盤或可傳輸的本質狀態(位元組流),序列化后的物件可以在網路、IPC(比如啟動另一個行程的Activity、Service和Reciver)之間進行傳輸,也可以存盤到本地,
- 序列化實作的兩種方式:實作Serializable/Parcelable介面,不同點如圖:

7. 如何解決View的事件沖突 ? 舉個開發中遇到的例子?
參考回答:
- 常見開發中事件沖突的有ScrollView與RecyclerView的滑動沖突、RecyclerView內嵌同時滑動同一方向,
- 滑動沖突的處理規則:
1.對于由于外部滑動和內部滑動方向不一致導致的滑動沖突,可以根據滑動的方向判斷誰來攔截事件,
2.對于由于外部滑動方向和內部滑動方向一致導致的滑動沖突,可以根據業務需求,規定何時讓外部View攔截事件,何時由內部View攔截事件,
3.對于上面兩種情況的嵌套,相對復雜,可同樣根據需求在業務上找到突破點, - 滑動沖突的實作方法:
1.外部攔截法:指點擊事件都先經過父容器的攔截處理,如果父容器需要此事件就攔截,否則就不攔截,具體方法:需要重寫父容器的onInterceptTouchEvent方法,在內部做出相應的攔截,
2.內部攔截法:指父容器不攔截任何事件,而將所有的事件都傳遞給子容器,如果子容器需要此事件就直接消耗,否則就交由父容器進行處理,具體方法:需要配合requestDisallowInterceptTouchEvent方法,
8. Looper死回圈為什么不會導致應用卡死?
參考回答:
- 主執行緒的主要方法就是訊息回圈,一旦退出訊息回圈,那么你的應用也就退出了,Looer.loop()方法可能會引起主執行緒的阻塞,但只要它的訊息回圈沒有被阻塞,能一直處理事件就不會產生ANR例外,
- 造成ANR的不是主執行緒阻塞,而是主執行緒的Looper訊息處理程序發生了任務阻塞,無法回應手勢操作,不能及時重繪UI,
- 阻塞與程式無回應沒有必然關系,雖然主執行緒在沒有訊息可處理的時候是阻塞的,但是只要保證有訊息的時候能夠立刻處理,程式是不會無回應的
9. Bitmap如何處理大圖,如一張30M的大圖,如何預防OOM?
參考回答:避免OOM的問題就需要對大圖片的加載進行管理,主要通過縮放來減小圖片的記憶體占用,
- BitmapFactory提供的加載圖片的四類方法(decodeFile、decodeResource、decodeStream、decodeByteArray)都支持BitmapFactory.Options引數,通過inSampleSize引數就可以很方便地對一個圖片進行采樣縮放
- 比如一張10241024的高清圖片來說,那么它占有的記憶體為102410244,即4MB,如果inSampleSize為 2,那么采樣后的圖片占用記憶體只有512512*4,即1MB(注意:根據最新的官方檔案指出,inSampleSize的取值應該總是為2的指數,即1、2、4、8等等,如果外界輸入不足為2的指數,系統也會默認選擇最接近2的指數代替,比如2)
- 綜合考慮,通過采樣率即可有效加載圖片,流程如下:
1.將BitmapFactory.Options的inJustDecodeBounds引數設為true并加載圖片;
2.從BitmapFactory.Options中取出圖片的原始寬高資訊,它們對應outWidth和outHeight引數;
3.根據采樣率的規則并結合目標View的所需大小計算出采樣率inSampleSize;
4.將BitmapFactory.Options的inJustDecodeBounds引數設為false,重新加載圖片;

10. 組件化中路由、埋點的實作?
參考回答:
- 因為在組件化中,各個業務模塊之間是各自獨立的, 并不會存在相互依賴的關系, 所以一個業務模塊是訪問不了其他業務模塊的代碼的, 如果想從 A 業務模塊的 A 頁面跳轉到 B 業務模塊的 B 頁面, 光靠模塊自身是不能實作的,這就需要一種跨組件通信方案—— 路由(Router)
- 路由
主要有以下兩種場景
第一種是:組件之間的頁面跳轉 (Activity 到 Activity, Fragment 到 Fragment, Activity 到 Fragment, Fragment 到 Activity) 以及跳轉時的資料傳遞 (基礎資料型別和可序列化的自定義型別別)
第二種是:組件之間的自定義類和自定義方法的呼叫(組件向外提供服務) - 其原理在于將分布在不同組件module中的某些類按照一定規則生成映射表(資料結構通常是Map,Key為一個字串,Value為類或物件),然后在需要用到的時候從映射表中根據字串從映射表中取出類或物件,本質上是類的查找,
- 埋點則是在應用中特定的流程收集一些資訊,用來跟蹤應用使用的狀況:
代碼埋點: 在某個事件發生時調SDK里面相應的介面發送埋點資料,百度統計、友盟、TalkingData、Sensors Analytics等第三方資料統計服務商大都采用這種方案,
全埋點: 全埋點指的是將Web頁面/App內產生的所有的、滿足某個條件的行為,全部上報到后臺服務器
可視化埋點: 通過可視化工具(例如Mixpanel)配置采集節點,在Android端自動決議配置并上報埋點資料,從而實作所謂的自動埋點
無埋點: 它并不是真正的不需要埋點,而是Android端自動采集全部事件并上報埋點資料,在后端資料計算時過濾出有用資料,
以上就是面試阿里,阿里面試官10道最常問的面試題,另外,在收集整理這些內容的時候,順便也將其他一些常見的大廠面試真題做了收集歸納和答案決議,如果有需要的朋友,可以順手點贊+評論文章后私信我,獲取領取方式!



最后還有一個面試小技巧:“如何引導面試官提問?”, 一般面試官在面試的候選者的時候,都會先將候選者的簡歷先過一遍,然后習慣性的根據候選者簡歷中體現的一些技術點,來由淺到深的提問,所以我們在書寫簡歷的時候,可以將自己一些擅長的技術點,體現到自己的專案經驗或者其它內容當中去,讓被動的面試,變得相對主動起來,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/227561.html
標籤:其他
