Android 面試題

1、RecyclerView和ListView的區(qū)別

緩存上:前者緩存的是View+ViewHolder+flag,不用每次調用findViewById,后者則只是緩存View

刷新數(shù)據(jù)方面,前者提供了局部刷新,后者則全部刷新

2、recyclerView嵌套卡頓解決如何解決

設置預加載的數(shù)量LinearLayoutManager.setInitialPrefetchItemCount(4),默認是預加載2個,

設置子項緩存,

設置自帶滑動沖突解決屬性rv.setHasFixedSize(true);? ? ??

? rv.setNestedScrollingEnabled(false);

可以完美解決,不過Google不推薦RecyClerView嵌套使用,需要嵌套盡量找類似于ExpandableListView 第三方控件來解決

3、談MVC ,MVP,MVVM

MVC:View是可以直接訪問Model的!從而,View里會包含Model信息,不可避免的還要包括一些 業(yè)務邏輯。 在MVC模型里,更關注的Model的不變,而同時有多個對Model的不同顯示,及View。所以,在MVC模型里,Model不依賴于View,但是 View是依賴于Model的。不僅如此,因為有一些業(yè)務邏輯在View里實現(xiàn)了,導致要更改View也是比較困難的,至少那些業(yè)務邏輯是無法重用的。

MVP:MVP 是從經典的模式MVC演變而來,它們的基本思想有相通的地方:Controller/Presenter負責邏輯的處理,Model提供數(shù)據(jù),View負 責顯示。作為一種新的模式,MVP與MVC有著一個重大的區(qū)別:在MVP中View并不直接使用Model,它們之間的通信是通過Presenter (MVC中的Controller)來進行的,所有的交互都發(fā)生在Presenter內部,而在MVC中View會從直接Model中讀取數(shù)據(jù)而不是通過 Controller。

MVVM:數(shù)據(jù)雙向綁定,通過數(shù)據(jù)驅動UI,M提供數(shù)據(jù),V視圖,VM即數(shù)據(jù)驅動層

4 、Android性能優(yōu)化

布局優(yōu)化: 減少布局層級,使用ViewStub提高顯示速度,布局服用,盡可能少使用warp_content,刪除空間中無用的屬性,避免過度繪制移除window默認背景,按需顯示展位圖,自定義View優(yōu)化,使用canvas.clipRect()識別可見區(qū)域

啟動速度:采用分布加載,異步加載,延期加載提高應用初始化速度,采用線程初始化數(shù)據(jù)等,合理的刷新機制

內存方面:防止內存泄露,使用一些第三方工具檢測解決

代碼優(yōu)化:遵循Java生命周期

安裝包優(yōu)化:刪除無用資源,優(yōu)化圖片,代碼混淆,避免重復庫存在,插件化

5、Fragment中add與replace的區(qū)別?

add不會重新初始化fragment,replace每次都會;

添加相同的fragment時,replace不會有任何變化,add會報IllegalStateException 異常;

replace 先 remove 掉相同 id 的所有 fragment,然后在add 當前的這個 fragment,而 add 是覆蓋前一個fragment。所以如果使用 add 一般會伴隨 hide()和show(),避免布局重疊;

使用 add,如果應用放在后臺,或以其他方式被系統(tǒng)銷毀,再打開時,hide()中引用的 fragment 會銷毀,所以依然會出現(xiàn)布局重疊 bug,可以使用 replace 或使用 add時,添加一個 tag 參數(shù);

6、如何避免OOM?

1.使用更加輕量的數(shù)據(jù)結構:如使用ArrayMap/SparseArray替代HashMap,HashMap更耗內存,因為它需要額外的實例對象來記錄Mapping操作,SparseArray更加高效,因為它避免了Key Value的自動裝箱,和裝箱后的解箱操作

2.便面枚舉的使用,可以用靜態(tài)常量或者注解@IntDef替代

3.Bitmap優(yōu)化:

a.尺寸壓縮:通過InSampleSize設置合適的縮放

b.顏色質量:設置合適的format,ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差異

c.inBitmap:使用inBitmap屬性可以告知Bitmap解碼器去嘗試使用已經存在的內存區(qū)域,新解碼的Bitmap會嘗試去使用之前那張Bitmap在Heap中所占據(jù)的pixel data內存區(qū)域,而不是去問內存重新申請一塊區(qū)域來存放Bitmap。利用這種特性,即使是上千張的圖片,也只會僅僅只需要占用屏幕所能夠顯示的圖片數(shù)量的內存大小,但復用存在一些限制,具體體現(xiàn)在:在Android 4.4之前只能重用相同大小的Bitmap的內存,而Android 4.4及以后版本則只要后來的Bitmap比之前的小即可。使用inBitmap參數(shù)前,每創(chuàng)建一個Bitmap對象都會分配一塊內存供其使用,而使用了inBitmap參數(shù)后,多個Bitmap可以復用一塊內存,這樣可以提高性能

4.StringBuilder替代String: 在有些時候,代碼中會需要使用到大量的字符串拼接的操作,這種時候有必要考慮使用StringBuilder來替代頻繁的“+”

5.避免在類似onDraw這樣的方法中創(chuàng)建對象,因為它會迅速占用大量內存,引起頻繁的GC甚至內存抖動

6.減少內存泄漏也是一種避免OOM的方法

7、如何實現(xiàn)進程保活

a: Service 設置成 START_STICKY kill 后會被重啟(等待5秒左右),重傳Intent,保持與重啟前一樣

b: 通過 startForeground將進程設置為前臺進程, 做前臺服務,優(yōu)先級和前臺應用一個級別,除非在系統(tǒng)內存非常缺,否則此進程不會被 kill

c: 雙進程Service: 讓2個進程互相保護對方,其中一個Service被清理后,另外沒被清理的進程可以立即重啟進程

d: 用C編寫守護進程(即子進程) : Android系統(tǒng)中當前進程(Process)fork出來的子進程,被系統(tǒng)認為是兩個不同的進程。當父進程被殺死的時候,子進程仍然可以存活,并不受影響(Android5.0以上的版本不可行)聯(lián)系廠商,加入白名單

e.鎖屏狀態(tài)下,開啟一個一像素Activity

8、說下冷啟動與熱啟動是什么,區(qū)別,如何優(yōu)化,使用場景等。

app冷啟動: 當應用啟動時,后臺沒有該應用的進程,這時系統(tǒng)會重新創(chuàng)建一個新的進程分配給該應用, 這個啟動方式就叫做冷啟動(后臺不存在該應用進程)。冷啟動因為系統(tǒng)會重新創(chuàng)建一個新的進程分配給它,所以會先創(chuàng)建和初始化Application類,再創(chuàng)建和初始化MainActivity類(包括一系列的測量、布局、繪制),最后顯示在界面上。

app熱啟動: 當應用已經被打開, 但是被按下返回鍵、Home鍵等按鍵時回到桌面或者是其他程序的時候,再重新打開該app時, 這個方式叫做熱啟動(后臺已經存在該應用進程)。熱啟動因為會從已有的進程中來啟動,所以熱啟動就不會走Application這步了,而是直接走MainActivity(包括一系列的測量、布局、繪制),所以熱啟動的過程只需要創(chuàng)建和初始化一個MainActivity就行了,而不必創(chuàng)建和初始化Application

冷啟動的流程

當點擊app的啟動圖標時,安卓系統(tǒng)會從Zygote進程中fork創(chuàng)建出一個新的進程分配給該應用,之后會依次創(chuàng)建和初始化Application類、創(chuàng)建MainActivity類、加載主題樣式Theme中的windowBackground等屬性設置給MainActivity以及配置Activity層級上的一些屬性、再inflate布局、當onCreate/onStart/onResume方法都走完了后最后才進行contentView的measure/layout/draw顯示在界面上

冷啟動的生命周期簡要流程::

Application構造方法 –> attachBaseContext()–>onCreate –>Activity構造方法 –> onCreate() –> 配置主體中的背景等操作 –>onStart() –> onResume() –> 測量、布局、繪制顯示

冷啟動的優(yōu)化主要是視覺上的優(yōu)化,解決白屏問題,提高用戶體驗,所以通過上面冷啟動的過程。能做的優(yōu)化如下:

減少 onCreate()方法的工作量

不要讓 Application 參與業(yè)務的操作

不要在 Application 進行耗時操作

不要以靜態(tài)變量的方式在 Application 保存數(shù)據(jù)

減少布局的復雜度和層級

減少主線程耗時

為什么冷啟動會有白屏黑屏問題?原因在于加載主題樣式Theme中的windowBackground等屬性設置給MainActivity發(fā)生在inflate布局當onCreate/onStart/onResume方法之前,而windowBackground背景被設置成了白色或者黑色,所以我們進入app的第一個界面的時候會造成先白屏或黑屏一下再進入界面。解決思路如下

1.給他設置 windowBackground 背景跟啟動頁的背景相同,如果你的啟動頁是張圖片那么可以直接給 windowBackground 這個屬性設置該圖片那么就不會有一閃的效果了

<style name=``"Splash_Theme"` `parent=``"@android:style/Theme.NoTitleBar"``>`

? ? <item name=``"android:windowBackground"``>@drawable/splash_bg</item>`

? ? <item name=``"android:windowNoTitle"``>``true``</item>`

</style>`


2.采用世面的處理方法,設置背景是透明的,給人一種延遲啟動的感覺。,將背景顏色設置為透明色,這樣當用戶點擊桌面APP圖片的時候,并不會"立即"進入APP,而且在桌面上停留一會,其實這時候APP已經是啟動的了,只是我們心機的把Theme里的windowBackground 的顏色設置成透明的,強行把鍋甩給了手機應用廠商(手機反應太慢了啦)

<style name=``"Splash_Theme"` `parent=``"@android:style/Theme.NoTitleBar"``>`

? ? <item name=``"android:windowIsTranslucent"``>``true``</item>`

? ? <item name=``"android:windowNoTitle"``>``true``</item>`

</style>`


3.以上兩種方法是在視覺上顯得更快,但其實只是一種表象,讓應用啟動的更快,有一種思路,將 Application 中的不必要的初始化動作實現(xiàn)懶加載,比如,在SpashActivity 顯示后再發(fā)送消息到 Application,去初始化,這樣可以將初始化的動作放在后邊,縮短應用啟動到用戶看到界面的時間

9、wait和 sleep 的區(qū)別

wait是Object的方法,wait是對象鎖,鎖定方法不讓繼續(xù)執(zhí)行,當執(zhí)行notify方法后就會繼續(xù)執(zhí)行,sleep 是Thread的方法,sleep 是使線程睡眠,讓出cpu,結束后自動繼續(xù)執(zhí)行

10、String,StringBuffer,StringBuilder的區(qū)別

String不可改變對象,一旦創(chuàng)建就不能修改

StringBuffer創(chuàng)建之后,可以去修改

StringBuilder也可修改,執(zhí)行效率高于StringBuffer,不安全

當字符賦值少使用String

字符賦值頻繁使用StringBuilder

當多個線程同步操作數(shù)據(jù),使用StringBuffer

11、進程和線程的區(qū)別

概念:進程包括多個線程,一個程序一個進程,多線程的優(yōu)點可以提高執(zhí)行效率,提高資源利用率

創(chuàng)建:Thread類和Runnable接口,

常用方法有:

start()用于啟動線程

run()調用線程對象中的run方法

join()合并插隊到當前線程

sellp()睡眠釋放cpu資源

setPriority()設置線程優(yōu)先級

12、隱式Intent與顯示Intent的區(qū)別

顯示intent效率高,系統(tǒng)直接精確定位要啟用的組件,但耦合度也高,如果通過這種方式調用一些系統(tǒng)組件的話,容易因為版本更新,類名、包名、包結構變化等原因導致程序崩潰。隱式意圖能夠降低程序的耦合度,但由于每次意圖執(zhí)行的時候,系統(tǒng)都會搜索所有可用的intentfilter,來查看是否有匹配的內容,所以效率更低。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容