2020上半年百度Android崗(初級到高級)面試真題全收錄

hkjhkjhkqqq 2022-01-07 14:15:26 阅读数:447

上半年 上半 半年 百度 android

加載WebView的同時,請求H5頁面數據。

因此常見的方法是:
全局WebView。
客戶端代理頁面請求。WebView初始化完成後向客戶端請求數據。
asset存放離線包。

除此之外還有一些其他的優化手段:
脚本執行慢,可以讓脚本最後運行,不阻塞頁面解析。
DNS鏈接慢,可以讓客戶端複用使用的域名與鏈接。
React框架代碼執行慢,可以將這部分代碼拆分出來,提前進行解析。

1.15如何優化自定義View

為了加速你的view,對於頻繁調用的方法,需要盡量减少不必要的代碼。先從onDraw開始,需要特別注意不應該在這裏做內存分配的事情,因為它會導致GC,從而導致卡頓。在初始化或者動畫間隙期間做分配內存的動作。不要在動畫正在執行的時候做內存分配的事情。

你還需要盡可能的减少onDraw被調用的次數,大多數時候導致onDraw都是因為調用了invalidate().因此請盡量减少調用invaildate()的次數。如果可能的話,盡量調用含有4個參數的invalidate()方法而不是沒有參數的invalidate()。沒有參數的invalidate會强制重繪整個view。

另外一個非常耗時的操作是請求layout。任何時候執行requestLayout(),會使得Android UI系統去遍曆整個View的層級來計算出每一個view的大小。如果找到有沖突的值,它會需要重新計算好幾次。另外需要盡量保持View的層級是扁平化的,這樣對提高效率很有幫助。

如果你有一個複雜的UI,你應該考慮寫一個自定義的ViewGroup來執行他的layout操作。與內置的view不同,自定義的view可以使得程序僅僅測量這一部分,這避免了遍曆整個view的層級結構來計算大小。

1.16TraceView的實現原理,分析數據誤差來源。

Andorid性能優化之traceview

2.Android Framework相關

2.1View的事件分發機制?滑動沖突怎麼解决?

觸摸事件對應的是MotionEvent類,事件的類型主要有如下三種:
ACTION_DOWN
ACTION_MOVE(移動的距離超過一定的閾值會被判定為ACTION_MOVE操作)
ACTION_UP
View事件分發本質就是對MotionEvent事件分發的過程。即當一個MotionEvent發生後,系統將這個點擊事件傳遞到一個具體的View上。

事件分發流程
事件分發過程由三個方法共同完成:
dispatchTouchEvent:方法返回值為true錶示事件被當前視圖消費掉;返回為super.dispatchTouchEvent錶示繼續分發該事件,返回為false錶示交給父類的onTouchEvent處理。
onInterceptTouchEvent:方法返回值為true錶示攔截這個事件並交由自身的onTouchEvent方法進行消費;返回false錶示不攔截,需要繼續傳遞給子視圖。如果return super.onInterceptTouchEvent(ev), 事件攔截分兩種情况:
1.如果該View存在子View且點擊到了該子View, 則不攔截, 繼續分發
給子View 處理, 此時相當於return false。
2.如果該View沒有子View或者有子View但是沒有點擊中子View(此時ViewGroup
相當於普通View), 則交由該View的onTouchEvent響應,此時相當於return true。

注意:一般的LinearLayout、 RelativeLayout、FrameLayout等ViewGroup默認不攔截, 而
ScrollView、ListView等ViewGroup則可能攔截,得看具體情况。
onTouchEvent:方法返回值為true錶示當前視圖可以處理對應的事件;返回值為false錶示當前視圖不處理這個事件,它會被傳遞給父視圖的onTouchEvent方法進行處理。如果return super.onTouchEvent(ev),事件處理分為兩種情况:
1.如果該View是clickable或者longclickable的,則會返回true, 錶示消費
了該事件, 與返回true一樣;
2.如果該View不是clickable或者longclickable的,則會返回false, 錶示不
消費該事件,將會向上傳遞,與返回false一樣。

注意:在Android系統中,擁有事件傳遞處理能力的類有以下三種:
Activity:擁有分發和消費兩個方法。
ViewGroup:擁有分發、攔截和消費三個方法。
View:擁有分發、消費兩個方法。

2.2如何解决View的事件沖突?

常見開發中事件沖突的有ScrollView與RecyclerView的滑動沖突、RecyclerView內嵌同時滑動同一方向。

滑動沖突的處理規則:
對於由於外部滑動和內部滑動方向不一致導致的滑動沖突,可以根據滑動的方向判斷誰來攔截事件。
對於由於外部滑動方向和內部滑動方向一致導致的滑動沖突,可以根據業務需求,規定何時讓外部View攔截事件,何時由內部View攔截事件。
對於上面兩種情况的嵌套,相對複雜,可同樣根據需求在業務上找到突破點。

滑動沖突的實現方法:
外部攔截法:指點擊事件都先經過父容器的攔截處理,如果父容器需要此事件就攔截,否則就不攔截。具體方法:需要重寫父容器的onInterceptTouchEvent方法,在內部做出相應的攔截。
內部攔截法:指父容器不攔截任何事件,而將所有的事件都傳遞給子容器,如果子容器需要此事件就直接消耗,否則就交由父容器進行處理。具體方法:需要配合requestDisallowInterceptTouchEvent方法。

2.3View的繪制流程?

DecorView被加載到Window中

  • 從Activity的startActivity開始,最終調用到ActivityThread的handleLaunchActivity方法來創建Activity,首先,會調用performLaunchActivity方法,內部會執行Activity的onCreate方法,從而完成DecorView和Activity的創建。然後,會調用handleResumeActivity,裏面首先會調用performResumeActivity去執行Activity的onResume()方法,執行完後會得到一個ActivityClientRecord對象,然後通過r.window.getDecorView()的方式得到DecorView,然後會通過a.getWindowManager()得到WindowManager,最終調用其addView()方法將DecorView加進去。
  • WindowManager的實現類是WindowManagerImpl,它內部會將addView的邏輯委托給WindowManagerGlobal,可見這裏使用了接口隔離和委托模式將實現和抽象充分解耦。在WindowManagerGlobal的addView()方法中不僅會將DecorView添加到Window中,同時會創建ViewRootImpl對象,並將ViewRootImpl對象和DecorView通過root.setView()把DecorView加載到Window中。這裏的ViewRootImpl是ViewRoot的實現類,是連接WindowManager和DecorView的紐帶。View的三大流程均是通過ViewRoot來完成的。

2.4Android中進程和線程的關系?區別?

  • 線程是CPU調度的最小單元,同時線程是一種有限的系統資源;而進程一般指一個執行單元,在PC和移動設備上指一個程序或者一個應用。
  • 一般來說,一個App程序至少有一個進程,一個進程至少有一個線程(包含與被包含的關系),通俗來講就是,在App這個工廠裏面有一個進程,線程就是裏面的生產線,但主線程(即主生產線)只有一條,而子線程(即副生產線)可以有多個。
  • 進程有自己獨立的地址空間,而進程中的線程共享此地址空間,都可以並發執行。

2.5為何需要IPC?多進程通信可能會出現的問題?

所有運行在不同進程的四大組件(Activity、Service、Receiver、ContentProvider)共享數據都會失敗,這是由於Android為每個應用分配了獨立的虛擬機,不同的虛擬機在內存分配上有不同的地址空間,這會導致在不同的虛擬機中訪問同一個類的對象會產生多份副本。比如常用例子(通過開啟多進程獲取更大內存空間、兩個或者多個應用之間共享數據、微信全家桶)。

一般來說,使用多進程通信會造成如下幾方面的問題:

  • 靜態成員和單例模式完全失效:獨立的虛擬機造成。
  • 線程同步機制完全失效:獨立的虛擬機造成。
  • SharedPreferences的可靠性下降:這是因為Sp不支持兩個進程並發進行讀寫,有一定幾率導致數據丟失。
  • Application會多次創建:Android系統在創建新的進程時會分配獨立的虛擬機,所以這個過程其實就是啟動一個應用的過程,自然也會創建新的Application。

2.6為什麼選擇Binder?
為什麼選用Binder,在討論這個問題之前,我們知道Android也是基於Linux內核,Linux現有的進程通信手段有以下幾種:

  • 管道:在創建時分配一個page大小的內存,緩存區大小比較有限;
  • 消息隊列:信息複制兩次,額外的CPU消耗;不合適頻繁或信息量大的通信;
  • 共享內存:無須複制,共享緩沖區直接附加到進程虛擬地址空間,速度快;但進程間的同步問題操作系統無法實現,必須各進程利用同步工具解决;
  • 套接字:作為更通用的接口,傳輸效率低,主要用於不同機器或跨網絡的通信;
  • 信號量:常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。 不適用於信息交換,更適用於進程中斷控制,比如非法內存訪問,殺死某個進程等;

既然有現有的IPC方式,為什麼重新設計一套Binder機制呢。主要是出於以上三個方面的考量:

  • 1、效率:傳輸效率主要影響因素是內存拷貝的次數,拷貝次數越少,傳輸速率越高。從Android進程架構角度分析:對於消息隊列、Socket和管道來說,數據先從發送方的緩存區拷貝到內核開辟的緩存區中,再從內核緩存區拷貝到接收方的緩存區,一共兩次拷貝,如圖:

而對於Binder來說,數據從發送方的緩存區拷貝到內核的緩存區,而接收方的緩存區與內核的緩存區是映射到同一塊物理地址的,節省了一次數據拷貝的過程,如圖:

共享內存不需要拷貝,Binder的性能僅次於共享內存。

  • 2、穩定性:上面說到共享內存的性能優於Binder,那為什麼不采用共享內存呢,因為共享內存需要處理並發同步問題,容易出現死鎖和資源競爭,穩定性較差。Socket雖然是基於C/S架構的,但是它主要是用於網絡間的通信且傳輸效率較低。Binder基於C/S架構 ,Server端與Client端相對獨立,穩定性較好。
  • 3、安全性:傳統Linux IPC的接收方無法獲得對方進程可靠的UID/PID,從而無法鑒別對方身份;而Binder機制為每個進程分配了UID/PID,且在Binder通信時會根據UID/PID進行有效性檢測。

Binder機制的作用和原理?

Linux系統將一個進程分為用戶空間和內核空間。對於進程之間來說,用戶空間的數據不可共享,內核空間的數據可共享,為了保證安全性和獨立性,一個進程不能直接操作或者訪問另一個進程,即Android的進程是相互獨立、隔離的,這就需要跨進程之間的數據通信方式。普通的跨進程通信方式一般需要2次內存拷貝,如下圖所示:

一次完整的 Binder IPC 通信過程通常是這樣:

  • 首先 Binder 驅動在內核空間創建一個數據接收緩存區。
  • 接著在內核空間開辟一塊內核緩存區,建立內核緩存區和內核中數據接收緩存區之間的映射關系,以及內核中數據接收緩存區和接收進程用戶空間地址的映射關系。
  • 發送方進程通過系統調用 copyfromuser() 將數據 copy 到內核中的內核緩存區,由於內核緩存區和接收進程的用戶空間存在內存映射,因此也就相當於把數據發送到了接收進程的用戶空間,這樣便完成了一次進程間的通信。

Binder框架中ServiceManager的作用?

Binder框架 是基於 C/S 架構的。由一系列的組件組成,包括 Client、Server、ServiceManager、Binder驅動,其中 Client、Server、Service Manager 運行在用戶空間,Binder 驅動運行在內核空間。如下圖所示:

  • Server&Client:服務器&客戶端。在Binder驅動和Service Manager提供的基礎設施上,進行Client-Server之間的通信。
  • ServiceManager(如同DNS域名服務器)服務的管理者,將Binder名字轉換為Client中對該Binder的引用,使得Client可以通過Binder名字獲得Server中Binder實體的引用。
  • Binder驅動(如同路由器):負責進程之間binder通信的建立,計數管理以及數據的傳遞交互等底層支持。

最後,結合Android跨進程通信:圖文詳解 Binder機制 的總結圖來綜合理解一下:

2.7AMS家族重要術語解釋。

1.ActivityManagerServices,簡稱AMS,服務端對象,負責系統中所有Activity的生命周期。
2.ActivityThread,App的真正入口。當開啟App之後,調用main()開始運行,開啟消息循環隊列,這就是傳說的UI線程或者叫主線程。與ActivityManagerService一起完成Activity的管理工作。
3.ApplicationThread,用來實現ActivityManagerServie與ActivityThread之間的交互。在ActivityManagerSevice需要管理相關Application中的Activity的生命周期時,通過ApplicationThread的代理對象與ActivityThread通信。
4.ApplicationThreadProxy,是ApplicationThread在服務器端的代理,負責和客戶端的ApplicationThread通信。AMS就是通過該代理與ActivityThread進行通信的。
5.Instrumentation,每一個應用程序只有一個Instrumetation對象,每個Activity內都有一個對該對象的引用,Instrumentation可以理解為應用進程的管家,ActivityThread要創建或暫停某個Activity時,都需要通過Instrumentation來進行具體的操作。
6.ActivityStack,Activity在AMS的棧管理,用來記錄經啟動的Activity的先後關系,狀態信息等。通過ActivtyStack决定是否需要啟動新的進程。
7.ActivityRecord,ActivityStack的管理對象,每個Acivity在AMS對應一個ActivityRecord,來記錄Activity狀態以及其他的管理信息。其實就是服務器端的Activit對象的映像。
8.TaskRecord,AMS抽象出來的一個“任務”的概念,是記錄ActivityRecord的棧,一個“Task”包含若幹個ActivityRecord。AMS用TaskRecord確保Activity啟動和退出的順序。如果你清楚Activity的4種launchMode,那麼對這概念應該不陌生。

2.8ActivityThread工作原理。

2.9廣播發送和接收的原理了解嗎?

  • 繼承BroadcastReceiver,重寫onReceive()方法。
  • 通過Binder機制向ActivityManagerService注册廣播。
  • 通過Binder機制向ActivityMangerService發送廣播。
  • ActivityManagerService查找符合相應條件的廣播(IntentFilter/Permission)的BroadcastReceiver,將廣播發送到BroadcastReceiver所在的消息隊列中。
  • BroadcastReceiver所在消息隊列拿到此廣播後,回調它的onReceive()方法。

2.10apk打包流程

1.通過AAPT工具進行資源文件(包括AndroidManifest.xml、布局文件、各種xml資源等)的打包,生成R.java文件。
2.通過AIDL工具處理AIDL文件,生成相應的Java文件。
3.通過Java Compiler編譯R.java、Java接口文件、Java源文件,生成.class文件。
4.通過dex命令,將.class文件和第三方庫中的.class文件處理生成classes.dex,該過程主要完成Java字節碼轉換成Dalvik字節碼,壓縮常量池以及清除冗餘信息等工作。
5.通過ApkBuilder工具將資源文件、DEX文件打包生成APK文件。
6.通過Jarsigner工具,利用KeyStore對生成的APK文件進行簽名。
7.如果是正式版的APK,還會利用ZipAlign工具進行對齊處理,對齊的過程就是將APK文件中所有的資源文件距離文件的起始距比特置都偏移4字節的整數倍,這樣通過內存映射訪問APK文件的速度會更快,並且會减少其在設備上運行時的內存占用。

2.11說下安卓虛擬機和java虛擬機的原理和不同點?

JVM、Davilk、ART三者的原理和區別
JVM 和Dalvik虛擬機的區別
JVM:.java -> javac -> .class -> jar -> .jar
架構: 堆和棧的架構.
DVM:.java -> javac -> .class -> dx.bat -> .dex
架構: 寄存器(cpu上的一塊高速緩存)

3.Android優秀三方庫源碼及架構設計

3.1原理性問題

網絡底層框架:OkHttp實現原理
網絡封裝框架:Retrofit實現原理
響應式編程框架:RxJava實現原理
圖片加載框架:Glide實現原理
事件總線框架:EventBus實現原理
內存泄漏檢測框架:LeakCanary實現原理
依賴注入框架:ButterKnife實現原理
依賴全局管理框架:Dagger2實現原理
數據庫框架:GreenDao實現原理
MVC MVP MVVM原理和區別?

3.2為什麼要在項目中使用OKHTTP這個庫?

1.OkHttp 提供了對最新的 HTTP 協議版本 HTTP/2 和 SPDY 的支持,這使得對同一個主機發出的所有請求都可以共享相同的套接字連接。
2.如果 HTTP/2 和 SPDY 不可用,OkHttp 會使用連接池來複用連接以提高效率。
3.OkHttp 提供了對 GZIP 的默認支持來降低傳輸內容的大小。
4.OkHttp 也提供了對 HTTP 響應的緩存機制,可以避免不必要的網絡請求。
5.當網絡出現問題時,OkHttp 會自動重試一個主機的多個 IP 地址。

3.3OKhttp針對網絡層有哪些優化?

3.4網絡請求緩存處理,okhttp如何處理網絡緩存的?

3.5從網絡加載一個10M的圖片,說下注意事項?

3.6WebSocket與socket的區別?

3.7Retrofit優勢

1、功能强大:
支持同步、异步
支持多種數據的解析 & 序列化格式
支持RxJava
2、簡潔易用:
通過注解配置網絡請求參數
采用大量設計模式簡化使用
3、可擴展性好:
功能模塊高度封裝
解耦徹底,如自定義Converters

3.8為什麼用Glide

1、多樣化媒體加載:不僅可以進行圖片緩存,還支持Gif、WebP、縮略圖,甚至是Video。
2、通過設置綁定生命周期:可以使加載圖片的生命周期動態管理起來。
3、高效的緩存策略:支持內存、Disk緩存,並且Picasso只會緩存原始尺寸的圖片,內Glide緩存的是多種規格,也就是Glide會根據你ImageView的大小來緩存相應大小的圖片尺寸。
4、內存開銷小:默認的Bitmap格式是RGB_565格式,而Picasso默認的是ARGB_8888格式,內存開銷小一半。

3.9Glide源碼機制的核心思想:

使用一個弱引用map activeResources來盛放項目中正在使用的資源。Lrucache中不含有正在使用的資源。資源內部有個計數器來顯示自己是不是還有被引用的情况,把正在使用的資源和沒有被使用的資源分開有什麼好處呢??因為當Lrucache需要移除一個緩存時,會調用resource.recycle()方法。注意到該方法上面注釋寫著只有沒有任何consumer引用該資源的時候才可以調用這個方法。那麼為什麼調用resource.recycle()方法需要保證該資源沒有任何consumer引用呢?glide中resource定義的recycle()要做的事情是把這個不用的資源(假設是bitmap或drawable)放到bitmapPool中。bitmapPool是一個bitmap回收再利用的庫,在做transform的時候會從這個bitmapPool中拿一個bitmap進行再利用。這樣就避免了重新創建bitmap,减少了內存的開支。而既然bitmapPool中的bitmap會被重複利用,那麼肯定要保證回收該資源的時候(即調用資源的recycle()時),要保證該資源真的沒有外界引用了。這也是為什麼glide花費那麼多邏輯來保證Lrucache中的資源沒有外界引用的原因。

3.10Glide內存緩存如何控制大小?

3.11加載bitmap過程(怎樣保證不產生內存溢出)

3.12Bitmap如何處理大圖,如一張30M的大圖,如何預防OOM?

3.13MVP與MVC的主要區別:

1、(最主要區別)View與Model並不直接交互,而是通過與Presenter交互來與Model間接交互。而在MVC中View可以與Model直接交互。
2、Presenter與View的交互是通過接口來進行的,更有利於添加單元測試。

3.14MVC->MVP->MVVM演進過程

MVC -> MVP -> MVVM 這幾個軟件設計模式是一步步演化發展的,MVVM 是從 MVP 的進一步發展與規範,MVP 隔離了MVC中的 M 與 V 的直接聯系後,靠 Presenter 來中轉,所以使用 MVP 時 P 是直接調用 View 的接口來實現對視圖的操作的,這個 View 接口的東西一般來說是 showData、showLoading等等。M 與 V已經隔離了,方便測試了,但代碼還不够優雅簡潔,所以 MVVM 就彌補了這些缺陷。在 MVVM 中就出現的 Data Binding 這個概念,意思就是 View 接口的 showData 這些實現方法可以不寫了,通過 Binding 來實現。

3.15MVC的情况下怎麼把Activity的C和V抽離?

3.16MVP 架構中 Presenter 定義為接口有什麼好處;

3.17MVP如何管理Presenter的生命周期,何時取消網絡請求?

3.18Fragment如果在Adapter中使用應該如何解耦?

3.19項目框架裏有沒有Base類,BaseActivity和BaseFragment這種封裝導致的問題,以及解决方法?

3.20從0設計一款App整體架構,如何去做?

3.21實現一個庫,完成日志的實時上報和延遲上報兩種功能,該從哪些方面考慮?

3.22你最優秀的工程設計項目,是怎麼設計和實現的;擴展,如何做成一個平臺級產品?


4.其他高頻面試題

4.1Android動畫框架實現原理。

4.2Activity-Window-View三者的差別?

4.3低版本SDK如何實現高版本api?

4.4Android的生命周期和啟動模式

4.5RecyclerView和ListView有什麼區別?局部刷新?前者使用時多重type場景下怎麼避免滑動卡頓。懶加載怎麼實現,怎麼優化滑動體驗。
ListView、RecyclerView區別?

4.6說說穀歌新推出的Room架構。

4.7Debug跟Release的APK的區別?

他高頻面試題
4.1Android動畫框架實現原理。

4.2Activity-Window-View三者的差別?

4.3低版本SDK如何實現高版本api?

4.4Android的生命周期和啟動模式

4.5RecyclerView和ListView有什麼區別?局部刷新?前者使用時多重type場景下怎麼避免滑動卡頓。懶加載怎麼實現,怎麼優化滑動體驗。
ListView、RecyclerView區別?

4.6說說穀歌新推出的Room架構。

4.7Debug跟Release的APK的區別?

版权声明:本文为[hkjhkjhkqqq]所创,转载请带上原文链接,感谢。 https://gsmany.com/2022/01/202201071415263627.html