該文章是自己在閱讀 Android性能優(yōu)化典范-第1季 時(shí)的讀書筆記日戈,Android性能優(yōu)化典范主要講了Android的渲染機(jī)制询张、內(nèi)存和GC以及電量優(yōu)化方面相關(guān)的內(nèi)容,因?yàn)閮?nèi)容比較龐雜浙炼,加上一些知識點(diǎn)需要花心思去理解份氧,所以在閱讀的時(shí)候唯袄,順便記錄一下自己的閱讀理解。
筆記條目
1蜗帜、Android?系統(tǒng)每隔?16ms?發(fā)出?VSYNC?信號恋拷,觸發(fā)硬件對?UI?的渲染。
2厅缺、1秒?=?1000ms?所以基于上面的規(guī)則蔬顾,每一秒?UI?應(yīng)該渲染?1000/16?=?60?(次),也就是我們經(jīng)车旯椋看到的?60hz?這個(gè)值阎抒,表示一秒內(nèi)刷新屏幕的次數(shù),用術(shù)語講?這叫刷新率(Refresh?Rate)消痛。
3且叁、刷新率這個(gè)值取決于硬件的固定參數(shù),一般的這個(gè)值為60fps,原因在于人眼與大腦無法感知超過60fps的界面更新秩伞。
4逞带、幀率是區(qū)別于刷新率的另一個(gè)概念,他代表每一秒GPU繪制操作的幀數(shù)
Note:兩者的區(qū)別在于刷新率表示屏幕會按照這個(gè)頻率去不停的刷新屏幕纱新,至于屏幕上顯示什么他控制不了展氓,幀率表示GPU(圖形處理器)一秒內(nèi)繪制的次數(shù),他倆前者負(fù)責(zé)按刷新率不停刷新界面脸爱,后者負(fù)責(zé)按幀率去不停繪制界面遇汞。
5、刷新率和幀率需要結(jié)合在一起工作簿废,才能讓視圖內(nèi)容呈現(xiàn)在屏幕空入。
6、GPU獲取圖形數(shù)據(jù)并繪制族檬,硬件負(fù)責(zé)把GPU生成的視圖數(shù)據(jù)拿出來顯示在屏幕上歪赢,這個(gè)過程一遍遍的在我們的手機(jī)中發(fā)生著。
如果屏幕刷新率和GPU幀率一致单料,那肯定是極好的埋凯,GPU每隔特定時(shí)間準(zhǔn)備好視圖數(shù)據(jù)。然后相應(yīng)的
扫尖,因?yàn)槠聊凰⑿侣矢鷰室恢掳锥裕裕藭r(shí)此刻屏幕正好也刷新界面换怖,視圖正常顯示甩恼。
但是大多數(shù)情況下,他倆的步調(diào)可能不一致,所以會出現(xiàn)錯(cuò)位的情況
此時(shí)媳拴,GPU?那邊準(zhǔn)備了數(shù)據(jù),但是屏幕這邊缺不能及時(shí)的顯示出來兆览。
7屈溉、界面渲染雙緩沖技術(shù)
一般我們在繪制UI的時(shí)候,都會采用一種稱為“雙緩沖”的技術(shù)抬探。雙緩沖意味著要使用兩個(gè)緩沖區(qū)(SharedBufferStack中)子巾,其中一個(gè)稱為Front?Buffer,另外一個(gè)稱為Back?Buffer小压。UI總是先在Back?Buffer中繪制线梗,然后再和Front?Buffer交換,渲染到顯示設(shè)備中怠益。理想情況下仪搔,這樣一個(gè)刷新會在16ms內(nèi)完成(60FPS)
更多詳情可參考 Android 顯示原理簡介?這篇文章
8、任何時(shí)候蜻牢,只要?View?中的繪制內(nèi)容發(fā)生變化烤咧,都會重新執(zhí)行創(chuàng)建?DisplayList?、渲染?DisplayList
9抢呆、Android?中的內(nèi)存模型分三級(這里的內(nèi)存應(yīng)該指的是堆內(nèi)存)分別為?Young?Generation煮嫌、Old?Generation、Permanent(常駐)?Generation抱虐,也就是說?Android?虛擬機(jī)中的堆內(nèi)存假如有125M,那么這125M會被指定為不同的類型昌阿,具體怎么指定,不用細(xì)究恳邀,他可以對每一塊區(qū)域設(shè)置一個(gè)變量懦冰,用于指示這個(gè)區(qū)域是屬于哪一級,這個(gè)純屬個(gè)人臆想轩娶,但說這么多儿奶,就是為了說明一個(gè)事實(shí),Android?堆內(nèi)存?那塊空間會被劃分為三種不同的類型鳄抒,Young闯捎、Old、Permanent许溅。
這里每個(gè)區(qū)域肯定一個(gè)具體的大小值瓤鼻,具體大小的分配就是?JVM?的事了,?Old?區(qū)贤重、Permanent?區(qū)的大小要大于?Young?區(qū)茬祷。
10、對內(nèi)存區(qū)域分級的意義并蝗,先不看官方介紹祭犯,個(gè)人推測一下也不難知道秸妥,這樣做就是為了更好的利用內(nèi)存空間這么如此寶貴的地方。被劃分成不同的區(qū)域后沃粗,我們每次?new
一個(gè)新對象時(shí)粥惧,毫無疑問,新對象分配的空間應(yīng)該在?Young?Genration?內(nèi)存區(qū)域內(nèi)最盅。
11突雪、該說說垃圾回收了。當(dāng)我們的程序不斷的運(yùn)行涡贱、不斷的創(chuàng)建對象咏删,Young?區(qū)的空間肯定有被用完的時(shí)候,此時(shí)?JVM?檢測到?內(nèi)存空間不夠用问词,就會啟動(dòng)?GC?督函,執(zhí)行垃圾回收,此時(shí)他很可能會對?Young?區(qū)的一些值做一些判斷戏售,看他們是不是被頻繁的使用侨核,如果是,他應(yīng)該會把這部分內(nèi)存空間標(biāo)記為?Old灌灾。同樣的道理搓译,Old?區(qū)的對象也可能被轉(zhuǎn)移到?Permanent?去,總之?JVM?這樣做就是為了提高對象創(chuàng)建的效率锋喜。
垃圾回收會把?Young?區(qū)中無用的對象給清理掉些己。
12、關(guān)于上述的推測嘿般,這里是胡凱博文中的原話段标,對照理解下:
Android里面是一個(gè)三級Generation的內(nèi)存模型,最近分配的對象會存放在Young?Generation區(qū)域炉奴,當(dāng)這個(gè)對象在這個(gè)區(qū)域停留的時(shí)間達(dá)到一定程度逼庞,它會被移動(dòng)到Old?Generation,最后到Permanent?Generation區(qū)域瞻赶。
每一個(gè)級別的內(nèi)存區(qū)域都有固定的大小赛糟,此后不斷有新的對象被分配到此區(qū)域,當(dāng)這些對象總的大小快達(dá)到這一級別內(nèi)存區(qū)域的閥值時(shí)砸逊,會觸發(fā)GC的操作璧南,以便騰出空間來存放其他新的對象。
13师逸、內(nèi)存泄露問題司倚。胡凱博文寫的很清楚明白,直接引用胡凱的原文
內(nèi)存泄漏指的是那些程序不再使用的對象無法被GC識別,這樣就導(dǎo)致這個(gè)對象一直留在內(nèi)存當(dāng)中动知,占用了寶貴的內(nèi)存空間皿伺。顯然,這還使得每級Generation的內(nèi)存區(qū)域可用空間變小盒粮,GC就會更容易被觸發(fā)心傀,從而引起性能問題。
內(nèi)存泄露為什么會導(dǎo)致性能問題拆讯,上面的這段話很精辟的指出來了。就是因?yàn)樾孤兜膶ο髸练e在內(nèi)存區(qū)养叛,隨著泄露的對象越來越多种呐,JVM?周期性的?GC?后發(fā)現(xiàn)內(nèi)存空間依舊滿滿的,此時(shí)就會發(fā)生大家常說的內(nèi)存溢出問題了弃甥。
其實(shí)垃圾回收器(GC)在很努力的回收內(nèi)存區(qū)中的無用對象爽室,但是每次掃描卻發(fā)現(xiàn)?那些泄露的對象一直被一些或者的對象所持有,所以內(nèi)存泄露問題淆攻,一定在開發(fā)中需要重視阔墩。
14、每次?GC?的時(shí)候瓶珊,其他所有線程都是暫停狀態(tài)啸箫,也就是說?GC操作會暫停其他任務(wù)。
開發(fā)?Tip
以上是自己在閱讀《Android性能優(yōu)化典范》時(shí)的筆記伞芹,感謝作者可以把視頻內(nèi)容轉(zhuǎn)化為更加容易理解的文章忘苛。
但是任何好文章,閱讀完應(yīng)該可以給讀者一些指導(dǎo)唱较,這篇文章中講了很多概念以及原理扎唾,下面就針對文章,總結(jié)一些開發(fā)過程中應(yīng)該遵循的一些建議南缓,以期讓自己的?App?具有更好的性能胸遇。
1、避免在?for?循環(huán)中給對象分配內(nèi)存汉形,直白一點(diǎn)就是說?不要在?for?循環(huán)中?new?對象纸镊,最好可以移動(dòng)到?for?之前。
2获雕、避免在自定義?View?時(shí)薄腻,在?onDraw?方法中執(zhí)行太復(fù)雜的邏輯操作。
3届案、避免在?onDraw?方法中?創(chuàng)建對象庵楷,因?yàn)樵诮缑胬L制時(shí),該方法可能會被大量的重復(fù)執(zhí)行,這樣會導(dǎo)致一瞬間產(chǎn)生大量的對象尽纽,從而導(dǎo)致堆空間中瞬間產(chǎn)生大量無用對象咐蚯,從而觸發(fā)?JVM?的?GC?操作。
Note:一些情況下弄贿,無法避免在?onDraw?方法中創(chuàng)建對象春锋,那么此時(shí)為了優(yōu)化性能,可以采取對象池的策略差凹,手動(dòng)緩存已創(chuàng)建的對象期奔,并加以復(fù)用,從而降低性能損失危尿。但是使用此方法呐萌,需要注意一點(diǎn),應(yīng)該及時(shí)的手動(dòng)清理對象池谊娇,否則可能會引起更加嚴(yán)重的內(nèi)存問題肺孤。
4、開發(fā)app的性能目標(biāo)就是保持60fps济欢,這意味著每一幀你只有16ms=1000/60的時(shí)間來處理所有的任務(wù)赠堵。所以我們的布局能簡單則簡單。
5法褥、考慮到過渡繪制茫叭,我們在寫布局?layout?時(shí),不應(yīng)該隨意的去為一些?View?設(shè)置?background半等,例如杂靶,當(dāng)我們的根布局已經(jīng)設(shè)置過一次背景色,那么子view默認(rèn)的背景色就是它了酱鸭,所以對于一些子?View?吗垮,如果它跟根布局背景顏色一致,那么該?View?就無需再設(shè)置背景色了凹髓,另外一些情況可能需要設(shè)置?selector烁登,此時(shí)默認(rèn)背景可以設(shè)置為?透明色。
6蔚舀、對于電量優(yōu)化饵沧,我們應(yīng)該減少喚醒屏幕的次數(shù)以及持續(xù)時(shí)間,使用?WeakLock?處理喚醒問題赌躺。
7狼牺、對一些非必須馬上執(zhí)行的操作,可以等待手機(jī)處于充電狀態(tài)或者電量充足時(shí)再執(zhí)行礼患。
8是钥、對一些零散的網(wǎng)絡(luò)請求掠归,可以打包一次操作,避免過多的無線信號引起的電量消耗悄泥。