綠鵝等大廠2020Android面試經驗(持續整理更新中)

1、Android 四大組件

Activity,Service,Content provider,broadcast receiver。 詳情

2. Activity的4種啓動方式

standard, singleTop, singleTask, singleInstance。詳情

3. Binder機制

Binder是Android系統上實現的一種IPC(Inter-process communication,進程間通信)機制。詳情

4. HIDL

HAL 接口定義語言(簡稱 HIDL,發音爲“hide-l”)是用於指定 HAL 和其用戶之間的接口的一種接口描述語言 (IDL)。HIDL 允許指定收集到接口和軟件包的類型和方法調用。從更廣泛的意義上來說,HIDL 是用於在可以獨立編譯的代碼庫之間進行通信的系統。HIDL 旨在用於進程間通信 (IPC)。詳情

5. Android的消息機制(Looper,Handler,Messagequeue)

Android系統本質上來說就是一個消息驅動的系統。Android使用消息機制實現線程間的通信,線程通過Looper建立自己的消息循環,MessageQueue是FIFO的消息隊列,Looper負責從MessageQueue中取出消息,並且分發到消息指定目標Handler對象。Handler對象綁定到線程的局部變量Looper,封裝了發送消息和處理消息的接口。詳情

6. final,finally,finalize的區別

final爲java修飾符,它可以用來定義變量,方法或者類,表示不可修改;
finally用在try/catch語句塊中,表示這段語句始終會被執行到;
finalize爲Object 類中定義的方法,在垃圾收集器刪除對象之前調用。

7. Android的進程優先級等級

分爲5個等級:Foreground,Visible,Service,Background,Empty。詳情

8. ArrayList的實現

Java集合框架圖

  • ArrayList是List接口的可變長數組實現,核心爲
    transient Object[] elementData;
  • ArrayList是一個泛型容器,新建ArrayList需要實例化泛型參數
  • ArrayList是線程不安全的。Ventor是線程安全的;
  • 瞭解ArrayList的擴容機制。詳情
9. 單例模式的實現方法
  • 懶漢模式(線程不安全)
  • 線程安全的懶漢模式(線程安全)
  • 餓漢模式(線程安全)
  • 靜態類內部加載(線程安全)
  • 枚舉方法(線程安全)
  • 雙重校驗鎖法(通常線程安全,低概率不安全)
  • 使用volatile關鍵字
  • 使用ThreadLocal關鍵字
  • 使用CAS鎖實現(線程安全)詳情
10. 原子操作的實現原理
  • 總線鎖
    當一個處理器在總線上輸出LOCK#信號時,其他處理器的請求將被阻塞住,那麼該
    處理器可以獨佔共享內存(總線鎖定把CPU和內存之間的通信鎖住了,這使得鎖定期間,其他處理器不能操作其他內存地址的數據,所以總線鎖定的開銷比較大);
  • 緩存鎖
    頻繁使用的內存會緩存在處理器的L1、L2和L3高速緩存裏,那麼原子操作就可以直接在處理器內部緩存中進行。所謂“緩存鎖定”是指內存區域如果被緩存在處理器的緩存行中,並且在Lock操作期間被鎖定,那麼當它執行鎖操作回寫到內存時,處理器不在總線上輸出LOCK#信號,而是修改內部的內存地址,並允許它的緩存一致性機制來保證操作的原子性。詳情
11. Java如何實現原子操作
  • 循環CAS
    JVM中的CAS操作利用了處理器提供的CMPXCHG指令來實現。自旋CAS實現的基本思路就是循環進行CAS操作直到成功爲止。CAS雖然很高效地解決了原子操作,但是CAS仍然存在三大問題:ABA問題;循環時間長開銷大;只能保證一個共享變量的原子操作。
  • 鎖機制
    鎖機制保證了只有獲得鎖的線程才能夠操作鎖定的內存區域。JVM內部實現了很多種鎖機制,有偏向鎖、輕量級鎖和互斥鎖。除了偏向鎖,JVM實現鎖的方式都用了循環CAS,即當一個線程想進入同步塊的時候使用循環CAS的方式來獲取鎖,當它退出同步塊的時候使用循環CAS釋放鎖。詳情
12. 談一談Android中的序列化

Android 提供了兩種方式來完成序列化與反序列化過程: Serializable Parcelable 。二者的 區別

13. 尾遞歸

傳統遞歸有兩個缺陷:效率低,佔內存;如果遞歸鏈過長,可能會statck overflow。
尾遞歸是一種特殊的遞歸,遞歸形式的調用都出現在函數的末尾,特點是在迴歸過程中不用做任何操作,大多數現代的編譯器會利用這種特點自動生成優化的代碼。在尾遞歸中,首先執行計算,然後執行遞歸調用,將當前步驟的結果傳遞給下一個遞歸步驟。這導致最後一個語句採用的形式(return (recursive-function params))。基本上,任何給定遞歸步驟的返回值與下一個遞歸調用的返回值相同詳情

14. IO的NIO的區別 詳情
IO NIO
面向字節流 面向緩衝區
阻塞 基於Selector的非阻塞
15. volitile關鍵字
  • 保證了不同線程對這個變量進行操作時的可見性,即一個線程修改了某個變量的值,這新值對其他線程來說是立即可見的;
  • 禁止進行指令重排序。詳情
16. String

使用字符串常量池,每當我們使用字面量(String s=”1”;)創建字符串常量時,JVM會首先檢查字符串常量池,如果該字符串已經存在常量池中,那麼就將此字符串對象的地址賦值給引用s(引用s在Java棧中)。如果字符串不存在常量池中,就會實例化該字符串並且將其放到常量池中,並將此字符串對象的地址賦值給引用s(引用s在Java棧中)。
使用字符串常量池,每當我們使用關鍵字new(String s=new String(”1”);)創建字符串常量時,JVM會首先檢查字符串常量池,如果該字符串已經存在常量池中,那麼不再在字符串常量池創建該字符串對象,而直接堆中複製該對象的副本,然後將堆中對象的地址賦值給引用s,如果字符串不存在常量池中,就會實例化該字符串並且將其放到常量池中,然後在堆中複製該對象的副本,然後將堆中對象的地址賦值給引用s。詳情

17. SurfaceFlinger

SurfaceFlinger是Android系統中的一個系統服務,這個系統服務主要實現了Surface的建立、控制、管理等功能,提供系統範圍內的surface composer功能,它能夠將各種應用程序的2D、3D surface進行組合。詳情

18. invalidate和postInvalidate

在主線程更新UI可以調用invalidate,子線程調用postInvalidate來更新UI。詳情

19. SurfaceView和TextureView
  • SurfaceView有自己的Surface,在WMS中有對應的WindowState,在SurfaceFlinger中有Layer。雖然在App端它仍在View hierachy中,但在Server端(WMS和SurfaceFlinger)中,它與宿主窗口是分離的。這樣的好處是對這個Surface的渲染可以放到單獨線程去做,渲染時可以有自己的GL context。缺點是Surface不在View hierachy中,顯示不受View的屬性控制,所以不能進行平移,縮放等變換,也不能放在其它ViewGroup中。SurfaceView 不能嵌套使用。
  • TextureView不會在WMS中單獨創建窗口,而是作爲View hierachy中的一個普通View,因此可以和其它普通View一樣進行移動,旋轉,縮放,動畫等變化。TextureView必須在硬件加速的窗口中。它顯示的內容流數據可以來自App進程或是遠端進程。TextureView重載了draw()方法,其中主要SurfaceTexture中收到的圖像數據作爲紋理更新到對應的HardwareLayer中。詳情
20. 爲何主線程Looper一直處於死循環但卻不卡死

主線程的MessageQueue沒有消息時,便阻塞在Looper的queue.next()中的nativePollOnce()方法裏,此時主線程會釋放CPU資源進入休眠狀態,直到下個消息到達或者有事務發生,通過往pipe管道寫端寫入數據來喚醒主線程工作。這裏採用的epoll機制,是一種IO多路複用機制,可以同時監控多個描述符,當某個描述符就緒(讀或寫就緒),則立刻通知相應程序進行讀或寫操作,本質同步I/O,即讀寫是阻塞的。 所以說,主線程大多數時候都是處於休眠狀態,並不會消耗大量CPU資源。詳情

21. init進程
start_kernel
init_post
run_init_process

init進程是Android系統中用戶空間的第一個進程,相關源碼位於system/core/init。它被賦予了很多極其重要的工作職責詳情

  1. 創建文件系統目錄並掛載相關的文件系統
  2. 屏蔽標準的輸入輸出
  3. 初始化內核log系統
  4. 調用property_init初始化屬性相關的資源
  5. 完成SELinux相關工作
  6. 重新設置屬性
  7. 創建epoll句柄
  8. 裝載子進程信號處理器
  9. 通過property_start_service啓動屬性服務
  10. 通過parser.ParseConfig(“/init.rc”)來解析init.rc
22. Zygote線程

在Android系統中,JavaVM(Java虛擬機)、應用程序進程以及運行系統的關鍵服務的SystemServer進程都是由Zygote進程來創建的,我們也將它稱爲孵化器。它通過fock(複製進程)的形式來創建應用程序進程和SystemServer進程,由於Zygote進程在啓動時會創建JavaVM,因此通過fock而創建的應用程序進程和SystemServer進程可以在內部獲取一個JavaVM的實例拷貝。詳情
ZygoteInit類的四大功能:

  • 綁定socket(registerZygoteSocket),以便接收新的Android應用的運行請求;
  • 預先加載應用程序框架中的類(preloadClasses,preloadResources)、平臺資源;
  • 啓動運行SystemServer(startSystemServer);
  • 監視UDS,處理新的應用處理請求。
23. findViewById

請參考詳情

24. View.post
  • View.post(Runnable)內部兩種判斷,如果當前View沒有繪製完成,通過類HandlerActionQueue內部將Runnabel緩存下來,否則就直接通過 mAttachInfo.mHandler 將這些 Runnable 操作 post 到主線程的 MessageQueue 中等待執行;
  • mAttachInfo.mHandler是ViewRootImpl中的成員變量,綁定的是主線程的Looper,所以View.post的操作會轉到主線程之中,自然可以作爲更新UI的根據了
  • Handler消息機制是不斷的從隊列中獲取Message對象,所以 View.post(Runnable) 中的 Runnable 操作肯定會在 performMeaure() 之後才執行,所以此時可以獲取到 View 的寬高。 詳情
25. OpenGL基本原理

OpenGL是將用數學語言和色彩等信息描述的三維空間物體通過計算轉換成二維圖像並顯示出來的程序庫。三維空間中的對象被描述成一系列的頂點(幾何對象)或像素(圖像)。OpenGL對數據進行幾個步驟的處理將其轉換成像素,這些數據存放在幀緩存區中形成最終需要顯示的圖形。

26. EGL作用

EGL 是渲染 API(如 OpenGL ES)和原生窗口系統之間的接口。通常來說,OpenGL 是一個操作 GPU 的 API,它通過驅動向 GPU 發送相關指令,控制圖形渲染管線狀態機的運行狀態,但是當涉及到與本地窗口系統進行交互時,就需要這麼一箇中間層,且它最好是與平臺無關的。 詳情
EGL爲OpenGL 和原生窗口系統之間的橋樑
EGL API 是獨立於 OpenGL ES的獨立的一套 API,其主要作用是爲 OpenGL指令創建 Context 、繪製目標 Surface 、配置 FrameBuffer 屬性、Swap 提交繪製結果等。EGL 提供如下機制:

  • 與設備原生窗口通信
  • 查詢繪製 surface 的可用類型和配置
  • 創建繪製 surface
  • 在 OpenGL ES 3.0 或其他渲染 API 之間同步渲染
  • 管理紋理貼圖等渲染資源
26. Context對象Context的繼承結構

Context的作用: 詳情

  • 獲取應用資源;
  • 訪問應用preference;
  • 管理私有的應用文件和目錄;
  • 獲取未編譯的應用資產;
  • 訪問系統服務;
  • 管理私有應用數據庫;
  • 使用應用權限。
27. JNI機制

JNI(Java Native Interface )標準是java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI 是本地編程接口,它使得在 Java 虛擬機 (VM) 內部運行的 Java 代碼能夠與用其它編程語言(如 C、C++ 和彙編語言)編寫的應用程序和庫進行交互操作。[詳情](https://blog.csdn.net/shulianghan/article/details/18964835

27. JNI之registerNativeMethods方法

傳統java Jni方式:1.編寫帶有native方法的Java類;2.使用javah命令生成.h頭文件;3.編寫代碼實現頭文件中的方法。這種方式必須遵循一定的方法命名格式,native方法名必須帶有較長的前綴,不易修改維護。
RegisterNatives方法能幫助你把c/c++中的方法隱射到Java中的native方法,而無需遵循特定的方法命名格式。應用層級的Java類別透過VM而呼叫到本地函數。一般是根據VM去尋找*.so裏的本地函數。如果需要連續呼叫很多次,每次都需要尋找一遍,會多花許多時間。此時,組件開發者可以自行將本地函數向VM進行登記,VM調registerNativeMethods()函數的用途有二:

  • 更有效率去找到函數;
  • 可在執行期間進行抽換。由於gMethods[]是一個<名稱,函數指針>對照表,在程序執行時,可多次呼叫registerNativeMethods()函數來更換本地函數之指針,而達到彈性抽換本地函數之目的。詳情
28. 硬件加速

硬件加速是指Android中在View上進行繪製的圖形圖像都使用GPU來進行繪製,使用硬件加速,在大部分時候都讓繪製更加流暢,但付出的代價是需要消耗更多的內存資源。硬件加速在API L14之上是默認開啓的,對於基本的View繪製,通過硬件加速可以增加繪圖的流程性,但是要注意的是,並不是所有的2D圖形繪製API都支持硬件加速。通過開發者選項中的“強制進行GPU渲染”,用戶可以爲全局打開硬件加速。Android上打開硬件加速之後View通過GPU渲染,關閉的話是使用Android中的2D圖形庫Skia。 由於硬件加速對某些2D繪圖API的不支持,Android系統提供了Application, Activity, Window, View四種級別的控制方式。[詳情](https://blog.csdn.net/qq_43666827/article/details/87353184)

29. this關鍵字

this關鍵字指向的是當前對象的引用。詳情

  • this.屬性名稱,指訪問類中的成員變量,用來區分成員變量和局部變量(重名問題);
  • this.方法名稱,用來訪問本類的成員方法;
  • this(),訪問本類的構造方法。
30. treble機制

Android 8.0 版本的一項新元素是 Project Treble。這是 Android 操作系統框架在架構方面的一項重大改變,旨在讓製造商以更低的成本更輕鬆、更快速地將設備更新到新版 Android 系統。Project Treble 適用於搭載 Android 8.0 及後續版本的所有新設備(這種新的架構已經在 Pixel 手機的開發者預覽版中投入使用)。詳情
Trebe 架構

31. 線程池

線程池的作用:詳情

  • 降低系統資源消耗,通過重用已存在的線程,降低線程創建和銷燬造成的消耗;
  • 提高系統響應速度,當有任務到達時,通過複用已存在的線程,無需等待新線程的創建便能立即執行;
  • 方便線程併發數的管控。因爲線程若是無限制的創建,可能會導致內存佔用過多而產生OOM,並且會造成cpu過度切換(cpu切換線程是有時間成本的(需要保持當前執行線程的現場,並恢復要執行線程的現場));
  • 提供更強大的功能,延時定時線程池。

持續更新中…
若有錯誤,歡迎留言指正,多謝!
本文參考了很多文章,每個問題的詳情附有參考鏈接。感謝原作者們,如有侵權,請及時聯繫。
歡迎收藏本文。轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章