因為實際開發與參考答案會有所不同,再者怕誤導大家,所以這些面試題答案還是自己去理解!面試官會針對履歷中提到的知識點由淺入深提問,所以不要背答案,多理解。
1、圖片的三級快取中,圖片載入到記憶體中,如果記憶體快爆了,會發生什麼事?怎麼處理?
- 參考答案:
首先我們要清楚圖片的三級快取是如何的
如果記憶體足夠時不回收。記憶體不夠時就回收軟引用物件
#2、記憶體中如果載入一張500*500的png高清圖片.應該是佔用多少的記憶體?
- 參考答案:
- #不考慮螢幕比的話:佔用記憶體=500 * 500 * 4 = 1000000B ≈ 0.95MB
- #考慮螢幕比的話:佔用記憶體= 寬度像素x (inTargetDensity / inDensity) x 高度像素x (inTargetDensity / inDensity)x 一個像素所佔的記憶體位元組大小
inDensity表示目標圖片的dpi(放在哪個資源資料夾下),inTargetDensity表示目標螢幕的dpi
3、WebView的效能最佳化?
4、 Bitmap如何處理大圖,如一張30M的大圖,如何預防OOM?
- 參考答案:
- 一個載入網頁的過程中,native、網路、後端處理、CPU都會參與,各自都有必要的工作和依賴關係;讓他們相互並行處理而不是相互阻塞才可以讓網頁加載更快:
- WebView初始化慢,可以在初始化同時先請求數據,讓後端和網路不要閒著。
- 常用JS 本地化及延遲加載,使用第三方瀏覽內核
- ##後端處理慢,可以讓伺服器分trunk輸出,在後端運算的同時前端也載入網路靜態資源。
- 腳本執行慢,就讓腳本在最後執行,不阻塞頁面解析。
- 同時,合理的預先載入、預先快取可以讓載入速度的瓶頸更小。
- WebView初始化慢,就隨時初始化好一個WebView待用。
- DNS和連結慢,想辦法重複使用客戶端使用的網域和連結。
參考回答:避免OOM的問題就需要對大圖片的載入進行管理,主要透過縮放來減少圖片的記憶體佔用。
BitmapFactory提供的載入圖片的四類方法(
- decodeFile、decodeResource、decodeStream、decodeByteArray)都支援BitmapFactory.Options參數,透過inSampleSize參數就可以很方便地對一個圖片進行採樣縮放
- 例如一張1024
- 1024的高畫質圖片來說。那麼它佔有的記憶體為102410244,即4MB,如果inSampleSize為2,那麼採樣後的圖片佔用記憶體只有5125124,即1MB( #註:根據最新的官方文件指出,inSampleSize的取值應該總是為2的指數,即1、2、4、8等等,如果外界輸入不足為2的指數,系統也會預設選擇最接近2的指數代替,例如2*)
- #綜合考量。透過取樣率即可有效載入圖片,流程如下
- 將BitmapFactory.Options的inJustDecodeBounds參數設為true並載入圖片
- 從BitmapFactory.Options中取出圖片的原始寬高信息,它們對應outWidth和outHeight參數
- 根據採樣率的規則並結合目標View的所需大小計算出取樣率inSampleSize
- 將BitmapFactory.Options的inJustDecodeBounds參數設為false,重新載入圖片
#5、記憶體回收機制與GC演算法(各種演算法的優缺點以及應用場景);GC原理時機以及GC物件
#6、記憶體外洩與記憶體溢出的差別? AS有什麼工具可以偵測記憶體外洩
- 參考答案:
- 記憶體判定物件可回收有兩種機制:
- #引用計數演算法:在物件中加入一個引用計數器,每當有一個地方引用它時,計數器值就加1;當引用失效時,計數器值就減1;任何時刻計數器為0的對象就是不可能再被使用的。然而在主流的Java虛擬機裡未選用引用計數演算法來管理內存,主要原因是它難以解決物件之間相互循環引用的問題,所以出現了另一種物件存活判定演算法。
- 可達性分析法:透過一系列稱為『GCRoots』的物件作為起始點,從這些節點開始向下搜索,搜尋所走過的路徑稱為引用鏈,當一個物件到GC Roots沒有任何引用鏈相連時,則證明此物件是不可用的。其中可作為GC Roots的對象:虛擬機器堆疊中所引用的對象,主要是指棧幀中的本地變數、本地方法堆疊中#Native方法引用的物件、方法區中類別靜態屬性所引用的物件、方法區中常數*引用的物件
- GC回收演算法有以下四種:
- ##分代收集演算法:是當前商業虛擬機器都採用的演算法,根據物件存活週期的不同,將Java堆劃分為新生代和老年代,並根據各個年代的特徵採用最適當的收集演算法。
- 新生代:大批對象死去,只有少量存活。使用‘複製演算法’,只需複製少量存活對象即可。
- 複製演算法:把可用記憶體依容量分成大小相等的兩塊,每次只使用其中的一塊。當這一塊的記憶體用盡後,把還存活著的物件『複製』到另外一塊上面,再將這一塊記憶體空間一次清理掉。 實作簡單,運作高效。在物件存活率較高時就要進行較多的複製操作,效率將會變低
- 老年代:對象存活率高。使用『標記—清理演算法』或『標記—整理演算法』,只需標記較少的回收對象即可。
- 標記-清除演算法:先『標記』出所有需要回收的對象,然後統一『清除』所有被標記的對象。 標記和清除兩個過程的效率都不高,清除之後會產生大量不連續的記憶體碎片,空間碎片太多可能會導致以後在程式運行過程中需要分配較大物件時,無法找到足夠的連續記憶體而不得不提前觸發另一次垃圾收集動作。
- 標記-整理演算法:先『標記』出所有需要回收的對象,然後進行『整理』,使得存活的對像都向一端移動,最後直接清理掉端邊界以外的記憶體。 標記整理演算法會將所有的存活物件移動到一端,並對不存活物件進行處理,因此其不會產生記憶體碎片
參考答案:
##7、效能最佳化,怎麼保證應用程式啟動不卡頓?黑白螢幕怎麼處理?
- 記憶體溢出(out of memory):是指程式在申請記憶體時,沒有足夠的記憶體空間供其使用,出現out of memory;例如申請了一個integer,但給它存了long才能存下的數,那就是記憶體溢位。
- 記憶體洩漏(memory leak):是指程式在申請記憶體後,無法釋放已申請的記憶體空間,一次記憶體外洩危害可以忽略,但記憶體洩漏堆積後果很嚴重,無論多少內存,遲早會被佔光。 memory leak會最終會導致out of memory!
- 尋找記憶體洩漏可以使用Android Studio 內建的
- AndroidProfiler工具或MAT
- 參考回答:
- 應用程式啟動速度,取決於你在application裡面時候做了什麼事情,例如你整合了很多sdk,而sdk的init操作都需要在主執行緒實現所以會有卡頓的感覺。在非必要的情況下可以把載入延後或則開啟子執行緒處理
- 另外,影響介面卡頓的兩大因素,分別是介面繪製和資料處理。
- 佈局優化(使用include,merge標籤,複雜佈局推薦使用ConstraintLayout等)
- onCreate() 中不執行耗時操作把頁面顯示的View 細分一下,放在AsyncTask 裡逐步顯示,用Handler 更好。這樣使用者的看到的就是有層次有步驟的一個個的 View 的展示,不會是先看到一個黑屏,然後一下顯示所有 View。最好做成動畫,效果更自然。
- 利用多執行緒的目的就是盡可能的減少 onCreate() 和 onReume() 的時間,使得使用者能盡快看到頁面,操作頁面。
- 減少主執行緒阻塞時間。
- 提高 Adapter 和 AdapterView 的效率。
- 黑白螢幕產生原因:當我們在啟動一個應用程式時,系統會去檢查是否已經存在這樣一個進程,如果不存在,系統的服務會先檢查startActivity中的intent的信息,然後在去創建進程,最後啟動Acitivy,即冷啟動。而啟動出現白黑屏的問題,就是在這段時間內產生的。系統在繪製頁面載入佈局之前,首先會初始化視窗(Window),而在進行這一步驟操作時,系統會根據我們設定的Theme來指定它的Theme 主題顏色,我們在Style中的設定就決定了顯示的是白屏還是黑屏。
- windowIsTranslucent和windowNoTitle,將這兩個屬性都設為true (會有明顯的卡頓體驗,不建議)
- 如果啟動頁只是是一張圖片,那麼為啟動頁專一設定一個新的主題,設定主題的android:windowBackground屬性為啟動頁背景圖即可
- 使用layer-list製作一張圖片launcher_layer. xml,將其設定為啟動頁專一主題的背景,並將其設定為啟動頁佈局的背景。
#8、強引用置為null,會不會被回收?
- 參考答案:
- 不會立即釋放物件所佔用的記憶體。 如果物件的參考被置為null,只是斷開了當前線程棧幀中對該對象的引用關係,而垃圾收集器是運行在後台的線程,只有當用戶線程運行到安全點(safe point )或安全區域才會掃描對象引用關係,掃描到對象沒有被引用則會標記對象,這時候仍然不會立即釋放該對象內存,因為有些對像是可恢復的(在finalize方法中恢復引用)。只有確定了物件無法恢復引用的時候才會清除物件記憶體。
9、ListView跟RecyclerView的差異
- 參考回答:
- 動畫區別:
- 在RecyclerView中,內建有許多動畫API,例如:notifyItemChanged(), notifyDataInserted(), notifyItemMoved()等等;如果需要自訂動畫效果,可以透過實作(RecyclerView.ItemAnimator類別)完成自訂動畫效果,然後呼叫RecyclerView.setItemAnimator();
- 但是ListView並沒有實現動畫效果,但我們可以在Adapter自己實作item的動畫效果;
- 刷新區別:
- ListView通常會刷新資料是用全域刷新notifyDataSetChanged(),這樣就會非常消耗資源;本身無法實現局部刷新,但是如果要在ListView實現局部刷新,依然是可以實現的,當一個item資料刷新時,我們可以在Adapter中,實作一個onItemChanged()方法,在方法裡面取得到這個item的position(可以透過getFirstVisiblePosition()),然後呼叫getView()方法來刷新這個item的資料;
- RecyclerView中可以實作局部刷新,例如:notifyItemChanged();
- 快取區別:
- RecyclerView比ListView多兩層緩存,支援多個離ItemView緩存,支援開發者自訂緩存處理邏輯,支援所有RecyclerView共用同一個RecyclerViewPool(緩存池)。
- ListView和RecyclerView快取機制基本上一致,但快取使用不同
10、ListView的adapter是什麼adapter##########參考答案:###### ############
- BaseAdapter:抽象類,實際開發中我們會繼承這個類別並且重寫相關方法,用得最多的一個適配器!
- ArrayAdapter:支援泛型運算,最簡單的一個適配器,只能展現一行文字〜
- SimpleAdapter:同樣具有良好擴充性的一個適配器,可以自訂多種效果!
- SimpleCursorAdapter:用來顯示簡單文字類型的listView,一般在資料庫那裡會用到,不過有點過時,不建議使用!
11、LinearLayout、FrameLayout、RelativeLayout效能對比,為什麼?
- 參考回答:
- RelativeLayout會讓子View呼叫2次onMeasure,LinearLayout 在有weight時,也會呼叫子View 2次onMeasure
- #RelativeLayout的子View如果高度和RelativeLayout不同,則會引發效率問題,當子View很複雜時,這個問題會更加嚴重。如果可以,盡量使用padding代替margin。
- 在不影響層級深度的情況下,使用LinearLayout和FrameLayout而不是RelativeLayout。
#
以上是11道Android效能優化面試題【附答案】的詳細內容。更多資訊請關注PHP中文網其他相關文章!