Android UI性能優(yōu)化

屏幕渲染機制

  • cpu(gpu sf暫統(tǒng)稱cpu)經(jīng)過各種運算征峦,將數(shù)據(jù)寫入一塊內(nèi)存中馆纳,這塊內(nèi)存叫做「幀緩沖」敌厘。
  • 幀緩沖可以理解為一個M*N矩陣滴须,數(shù)據(jù)從上到下一行一行保存舌狗。
  • 屏幕在顯示的時候,從上到下逐行掃描扔水,依次顯示在屏幕上痛侍,我們把這樣的一屏數(shù)據(jù)叫做「一幀」。
  • 當(dāng)一幀數(shù)據(jù)渲染完后魔市,就開始新一輪掃描主届,如果CPU「正好」(不正好后面再說)也把下一幀數(shù)據(jù)寫入幀緩沖赵哲,那么就會顯示下一幀畫面,如此循環(huán)君丁,我們就看到了不斷變化的畫面枫夺,也就是圖像。

過程很簡單谈截,執(zhí)行起來卻很難筷屡,因為這里有兩個問題,撕裂卡頓簸喂,為什么毙死?

  • 如果當(dāng)屏幕渲染到一半的時候,cpu已經(jīng)整理好了下一幀的數(shù)據(jù)喻鳄,給到幀緩沖扼倘,這時屏幕繼續(xù)從幀緩沖中一半的位置開始讀取數(shù)據(jù),這時畫面就會顯示異常除呵,這種兩個圖像重合的的問題叫作圖像撕裂再菊。
  • 如果當(dāng)屏幕渲染完一幀畫面,cpu還沒整理好下一幀數(shù)據(jù)給到幀緩沖颜曾,這時屏幕繼續(xù)從幀緩沖中讀取數(shù)據(jù)渲染纠拔,顯示的還是上一幀的數(shù)據(jù),這時用戶就會感覺到卡頓泛豪。

那你就會有個疑問了

  • 這cpu怎么這么笨稠诲,屏幕都沒把數(shù)據(jù)渲染完,干嘛把數(shù)據(jù)換了诡曙?
  • 屏幕怎么這么傻臀叙,數(shù)據(jù)都被換了,怎么不從頭讀取呢价卤?

這是因為"現(xiàn)代計算機之父"馮·諾依曼提出了計算機的體系結(jié)構(gòu): 計算機由運算器劝萤,存儲器,控制器慎璧,輸入設(shè)備和輸出設(shè)備構(gòu)成床嫌,每部分各司其職。

  • 屏幕的作用就是渲染胸私,不管外界怎么變化既鞠,它就是一行一行的渲染。
  • cpu的任務(wù)就是運算盖文,運算好了把數(shù)據(jù)丟給幀緩沖嘱蛋,繼續(xù)運算。

那能不能讓cpu停下來?
當(dāng)然可以洒敏,但是不劃算龄恋,因為這樣就等于把cpu的長處給扼殺了。

等等凶伙,有個問題郭毕,你說當(dāng)兩個圖像重合的的問題叫作撕裂,那不是從第二幀開始函荣,時時刻刻都在撕裂?

  • 好吧显押,我說錯了,有一點忘記說了傻挂,應(yīng)該有個時間乘碑,在這個時間內(nèi)渲染完一幀,畫面看起來就是連續(xù)的金拒,這個時間大約是16ms兽肤。

為什么是16ms?

  • 這是因為人眼與大腦之間的協(xié)作無法感知超過60fps的畫面更新。12fps大概類似手動快速翻動書籍的幀率绪抛,這明顯是可以感知到不夠順滑的资铡。24fps使得人眼感知的是連續(xù)線性的運動,這其實是歸功于運動模糊的效果幢码。24fps是電影膠圈通常使用的幀率笤休,因為這個幀率已經(jīng)足夠支撐大部分電影畫面需要表達的內(nèi)容,同時能夠最大的減少費用支出症副。但是低于30fps是無法順暢表現(xiàn)絢麗的畫面內(nèi)容的宛官,此時就需要用到60fps來達到想要的效果,當(dāng)然超過60fps是沒有必要的瓦糕。

fps是啥玩意兒?這里說兩個概念

  • 屏幕刷新率(Hz):屏幕在一秒內(nèi)刷新的次數(shù)腋么,Android手機一般都是60Hz咕娄,也就是一秒刷新60次,當(dāng)然也有高刷的珊擂,但是60Hz足矣圣勒。

  • 幀速率(FPS):cpu在一秒內(nèi)合成的幀數(shù),比如60FPS摧扇,就是60 frame per sconds圣贸,意思就是一秒合成60幀。如上所述扛稽,當(dāng)屏幕刷新率大于幀速率的時候吁峻,會發(fā)生卡頓;屏幕刷新率小于幀速率的時候,會發(fā)生撕裂用含。那么怎么解決這個問題呢矮慕?

怎么解決呢?Vsync 和 雙緩沖

雙緩沖+Vsync

  • 屏幕正在從前緩沖讀取第一幀數(shù)據(jù)并渲染啄骇,此時cpu計算完第二幀數(shù)據(jù)痴鳄,放在后緩沖,等待VSYNC信號缸夹。
  • 屏幕將第一幀數(shù)據(jù)渲染完畢痪寻,發(fā)出VSYNC信號,cpu收到VSYNC信號虽惭,將后緩沖的第二幀數(shù)據(jù)復(fù)制到前緩沖橡类。
  • 同時屏幕繼續(xù)繪制第二幀數(shù)據(jù),cpu開始計算下一幀數(shù)據(jù)趟妥,循環(huán)往復(fù)猫态。

牛~~,雙緩沖+Vsync解決了撕裂問題披摄,但是并沒有解決卡頓的問題,當(dāng)cpu收到Vsync信號后亲雪,如果cpu還沒有計算完,也肯定就不會交換前后緩沖的數(shù)據(jù)疚膊,也就是說义辕,屏幕再次讀取的還是前緩沖的數(shù)據(jù),也就是兩次顯示了一樣的畫面寓盗,也就是產(chǎn)生了卡頓灌砖。
是的,卡頓問題是解決不了的傀蚌,只能優(yōu)化基显。

還能怎么優(yōu)化?三緩沖 善炫!
首先要清楚下撩幽,Android屏幕繪制流程。

  1. 任何一個View都是依附于window的
  2. 一個window對應(yīng)一個surface
  3. view的measure箩艺、layout窜醉、draw等均是計算數(shù)據(jù),這些是cpu干的事
  4. cpu把這些事干好后艺谆,在經(jīng)過一系列計算將數(shù)據(jù)轉(zhuǎn)交給gpu
  5. gpu將數(shù)據(jù)柵格化后榨惰,就交給SurfeceFlinger(以下簡稱SF)
  6. SF將多個surfece數(shù)據(jù)合并處理后,就放入后緩沖區(qū)
  7. 屏幕以固定頻率從前緩沖區(qū)拿出數(shù)據(jù)渲染静汤,渲染完畢后發(fā)送VSYNC琅催,此時前后緩沖區(qū)數(shù)據(jù)交換居凶,屏幕繪制下一幀。

上述7步是建立在開啟硬件加速的情況下的恢暖,如果沒有硬件加速排监,就去掉gpu部分,就可以簡單理解為cpu直接將數(shù)據(jù)轉(zhuǎn)交給sf杰捂,我們簡單整理一下數(shù)據(jù)的傳遞流程:
「cpu -> gpu -> display」舆床,而且我們看到,cpu和gpu是排隊工作的嫁佳,它倆和屏幕是并行工作的挨队。好,我們來看發(fā)生卡頓(jank)的場景

雙緩沖卡頓場景

  • 我們可以將Display那一行看作是前緩沖蒿往,將GPU和CPU兩行疊加起來看作是后緩沖(因為它倆排隊使用)盛垦,將VSYNC線隔離開的豎行看作一個幀。
  • 我們看到瓤漏,在第一幀里面腾夯,GPU墨跡了半天沒搞完,以至于在第二幀里面蔬充,Display(屏幕)顯示的還是第一幀的A數(shù)據(jù)蝶俱,此時就產(chǎn)生了Jank(卡頓),并且在一個vsync信號過來后饥漫,cpu什么都沒做榨呆,因為gpu占著后緩沖(那個綠色的長B塊),所以cpu只能再等下一個vsync庸队,在下一個vsync里面积蜻,cpu終于拿到了后緩沖的使用權(quán),但是cpu計算時間比較長彻消,導(dǎo)致了gpu時間不夠用竿拆,數(shù)據(jù)又沒算完,再次發(fā)生了卡頓宾尚,可以說丙笋,這次卡頓直接受到了第一次卡頓的影響。
  • 試想: 如果在第一次卡頓的時候央勒,cpu也能計算數(shù)據(jù),那么澳化,第二次卡頓可能就不存在了崔步,因為cpu已經(jīng)在第一次卡頓的時候把藍色的A給計算完了,第二次完全可以讓gpu獨自計算(綠色的A)缎谷,就不存在因為排隊導(dǎo)致的時間不夠用了井濒,但是灶似!cpu和gpu共用后緩沖,這就導(dǎo)致它們只能輪流使用后緩沖瑞你,怎么解決呢酪惭?再加一個后緩沖區(qū),讓cpu者甲、gpu各用一塊春感。

我們來看引入三緩沖后的效果:


三緩沖使用效果
  • 我們看到,在第一次jank內(nèi)虏缸,cpu使用了第三塊緩沖區(qū)鲫懒,自己計算了C幀的數(shù)據(jù),假如此時沒有三緩沖刽辙,那么cpu就只能再繼續(xù)等下一個vsync信號窥岩,也就是在圖中藍色A塊的地方,才能開始計算C幀數(shù)據(jù)宰缤,就又引發(fā)下一次卡頓颂翼。我們看到,通過引入三緩沖慨灭,雖然不能避免卡頓問題朦乏,但是卻可以大幅優(yōu)化卡頓問題,尤其是避免連續(xù)卡頓缘挑。
  • 但是集歇,三緩沖也有缺點,就是耗資源语淘,所以系統(tǒng)并非一直開啟三緩沖诲宇,要想真正解決問題,還需要在cpu層對數(shù)據(jù)盡量優(yōu)化惶翻,從而減小cpu和gpu的計算量姑蓝,比如:View盡量扁平化,少嵌套吕粗,少在UI線程做耗時操作等纺荧。

源碼層面看cpu做了哪些事
請看這篇文章,View的加載流程
從這里我們可以看出颅筋,View加載過程中宙暇,使用到的耗時操作

  • IO操作(讀取布局文件)
  • Xml解析(解析布局文件)
  • 使用了遞歸(遞歸查找每一個View)。
  • 反射(使用反射初始化view)

解決IO操作和Xml解析
如果在可以的情況下议泵,不推薦使用Xml來寫布局占贫,推薦使用代碼直接new。但是這樣一來可維護性大大降低先口。
借用此思想型奥,github上也有一個由掌閱發(fā)布的開源庫:https://github.com/iReaderAndroid/X2C

  • 為了即保留xml的優(yōu)點瞳收,又解決它帶來的性能問題,我們開發(fā)了X2C方案厢汹。即在編譯生成APK期間螟深,將需要翻譯的layout翻譯生成對應(yīng)的java文件,這樣對于開發(fā)人員來說寫布局還是寫原來的xml烫葬,但對于程序來說界弧,運行時加載的是對應(yīng)的java文件。 ????我們采用APT(Annotation Processor Tool)+ JavaPoet技術(shù)來完成編譯期間【注解】->【解注解】->【翻譯xml】->【生成java】整個流程的操作厘灼。

RecyclerView優(yōu)化
RecyclerView一些你可能需要知道的優(yōu)化技術(shù)
參考:
Android 性能優(yōu)化必知必會
性能優(yōu)化系列總篇
Android性能優(yōu)化
一篇小短文夹纫,帶你了解屏幕刷新背后的故事
Android UI性能優(yōu)化實戰(zhàn) 識別繪制中的性能問題
Android UI性能優(yōu)化 檢測應(yīng)用中的UI卡頓
Google 發(fā)布 Android 性能優(yōu)化典范
Android性能優(yōu)化

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市设凹,隨后出現(xiàn)的幾起案子舰讹,更是在濱河造成了極大的恐慌,老刑警劉巖闪朱,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件月匣,死亡現(xiàn)場離奇詭異,居然都是意外死亡奋姿,警方通過查閱死者的電腦和手機锄开,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來称诗,“玉大人萍悴,你說我怎么就攤上這事≡⒚猓” “怎么了癣诱?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長袜香。 經(jīng)常有香客問我撕予,道長,這世上最難降的妖魔是什么蜈首? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任实抡,我火速辦了婚禮,結(jié)果婚禮上欢策,老公的妹妹穿的比我還像新娘吆寨。我一直安慰自己,他們只是感情好踩寇,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布啄清。 她就那樣靜靜地躺著,像睡著了一般姑荷。 火紅的嫁衣襯著肌膚如雪盒延。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天鼠冕,我揣著相機與錄音添寺,去河邊找鬼。 笑死懈费,一個胖子當(dāng)著我的面吹牛计露,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播憎乙,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼票罐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了泞边?” 一聲冷哼從身側(cè)響起该押,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎阵谚,沒想到半個月后蚕礼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡梢什,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年奠蹬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗡午。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡囤躁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出荔睹,到底是詐尸還是另有隱情狸演,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布应媚,位于F島的核電站严沥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏中姜。R本人自食惡果不足惜消玄,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望丢胚。 院中可真熱鬧翩瓜,春花似錦、人聲如沸携龟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽峡蟋。三九已至坟桅,卻和暖如春华望,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仅乓。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工赖舟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人夸楣。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓宾抓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親豫喧。 傳聞我的和親對象是個殘疾皇子石洗,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容