Android面試一天一題(11 Day)

遇到一個從快播出來的Android開發(fā),有11年的開發(fā)經(jīng)驗,咋一看不管是資歷還是經(jīng)歷都挺嚇人的。但和他共處一段時間后,發(fā)現(xiàn)他完全沒有體現(xiàn)出11年工作經(jīng)驗的優(yōu)勢,相反還常常犯一些低級的錯誤,如在ListView中加載本地的圖片(大圖)時不使用異步線程,而是直接setImageResource。而他工作和為人都很努力,對分配的工作都很認真,但效果卻常常不盡如人意,不管是和Android特性相關(guān)的代碼還是純邏輯的代碼,他都常常犯一些低級的錯誤(這些錯誤都是普遍認為一個11年工作經(jīng)驗的人不應(yīng)該犯的)。

后來我經(jīng)常思考,是什么樣的原因?qū)е乱粋€人的工作年限和水平并不能成正比。我想到有兩個方面:

  1. 看待問題的眼界過窄,只能看到當前的可見的問題。(或者說他思考問題的角度和方式有較大的局限)
  1. 技術(shù)的要點沒有掌握,常常找不到合理的解決問題的方案。

這兩點都是需要慢慢地提升和積累,當一個人長時間在思維和眼界上沒有進步,技術(shù)也只懂些皮毛(或者只是會用),那么他工作越長時間他的優(yōu)勢反而越不明顯,甚至變成劣勢。

面試題:如何優(yōu)化ListView的性能?

在回答這個問題前,我認為很有必要和大家講幾點和getView相關(guān)的問題。我們設(shè)置或者優(yōu)化ListView的性能很多時候都是在getView中完成的,反過來說就是很多性能問題都是由于沒有正確使用getView造成的。

public View getView(int position, View convertView, ViewGroup parent)

所以我們不妨先思考一下如下的幾個問題:

在一次顯示ListView的界面時,getView會被執(zhí)行幾次?

每次getView執(zhí)行時間應(yīng)該控制在多少毫秒之內(nèi)?

getView中設(shè)置listener要注意什么?

首先我們要知道ListView的ItemView有一個復(fù)用機制,簡單看如下圖所示,ListView中有一個RecycleBin類復(fù)負回收不可見且可能被再次使用的ItemView,由ScrapView存儲。


所以我在們設(shè)置Listener進就要注意,使用convertView時需要重新設(shè)置一個Listener,保括一些數(shù)據(jù)也需要重設(shè)置,不然可能會顯示之前那個ItemView在回收前的狀態(tài)。

在繪制ListView前往往要計算它的高度,所以一個ListView界面上可以看到6個ItemView,但是getView的執(zhí)行次數(shù)卻有可能是12次,多出的次數(shù)用來計算高度(這個可以通過設(shè)置ListView的height為0來避免)。所以要避免在getView中進行邏輯運算,兩次計算同一邏輯完全是浪費。

每個getView的執(zhí)行時間更是少得可憐,很多人可能對這個時間沒有概念,我可以簡單的給大算一下:

1秒之內(nèi)屏幕可以完成30幀的繪制,人才能看到它比較流暢(蘋果是接近60幀,高于60之后人眼也無法分辨)。
每幀可使用的時間:1000ms/30 = 33.33 ms
每個ListView一般要顯示6個ListItem,加上1個重用convertView:33.33ms/7 = 4.76ms

即是說,每個getView要在4.76ms內(nèi)完成工作才會較流暢,但是事實上,每個getView間的調(diào)用也會有一定的間隔(有可能是由于handler在處理別的消息),UI的handler處理不好的話,這個間隔也可難會很大(0ms-200ms)。結(jié)論就是,留給getView使用的時間應(yīng)該在4ms之內(nèi),如果不能控制在這之內(nèi)的話,ListView的滑動就會有卡頓的現(xiàn)象。

了解了這幾個問題,現(xiàn)在我們回來這次主要考查的面試題上,如何進行ListView的性能優(yōu)化,讓它滑動更加流暢。大家一般常用如下方法:

  1. 重用ConvertView;
  1. 使用View Holder模式;
  2. 使用異步線程加載圖片(一般都是直接使用圖片庫加載,如Glide, Picasso);

我認為這些是面試者必備的知識點,如果連這些都說不清楚的話,也沒有必要再深入問了。針對面試者的回答,可以適當選一兩點追問一下,看是否真正明白。如:ViewHolder為什么能夠起到優(yōu)化性能的作用?

除此之前還有一些優(yōu)化建議:

  1. 在adapter的getView方法中盡可能的減少邏輯判斷,特別是耗時的判斷;
  1. 避免GC(可以從LOGCAT查看有無GC的LOG);
  2. 在快速滑動時不要加載圖片;
  3. 將ListView的scrollingCache和animateCache這兩個屬性設(shè)置為false(默認是true);
  4. 盡可能減少List Item的Layout層次(如可以使用RelativeLayout替換LinearLayout,或使用自定的View代替組合嵌套使用的Layout);

關(guān)于第4點,發(fā)現(xiàn)在一些型號的手機(如華為的P7)上特別管用,當其也優(yōu)化都做完之后,有無這兩項設(shè)置滑動的卡頓情況有明顯不同。

<Listview
 android:scrollingCache="false" 
 android:animationCache="false"

小結(jié)

關(guān)于ListView有很多方面可以考察面試者,因為它實在是用的太頻繁了,雙方都能對某個問題點進行展開。如果一個面試者都沒有做過ListView優(yōu)化,那么如果不是他寫的代碼太少就是他使用ListView加載的數(shù)據(jù)太簡單(可能只有幾十項),其本上沒有其他選項。所以這一題是很能看出面試者的項目經(jīng)驗和實際的開發(fā)水平,屬于面試必考題之一。

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容