測(cè)與優(yōu)化技巧)
引言Android 應(yīng)用的性能優(yōu)化是開(kāi)發(fā)過(guò)程中至關(guān)重要的一環(huán)而幀率Frame Rate是評(píng)估應(yīng)用性能的一個(gè)關(guān)鍵指標(biāo)。在本文中我們將深入探討如何監(jiān)測(cè) Android 應(yīng)用的幀率以及如何通過(guò)代碼示例來(lái)優(yōu)化應(yīng)用的性能。什么是幀率幀率是指在一秒內(nèi)應(yīng)用程序能夠渲染的圖像幀數(shù)量。通常以FPSFrames Per Second表示。例如一個(gè)應(yīng)用在每秒內(nèi)渲染了60幀那么它的幀率就是60 FPS。幀率越高用戶(hù)體驗(yàn)越流暢但幀率的穩(wěn)定性也同樣重要。為什么幀率重要在用戶(hù)體驗(yàn)中幀率的高低直接關(guān)系到應(yīng)用的響應(yīng)速度和視覺(jué)效果。然而不僅要追求較高的幀率還需要關(guān)注幀率的穩(wěn)定性。下面我們將詳細(xì)探討這兩個(gè)方面的重要性。幀率的絕對(duì)值幀率的絕對(duì)值表示在一秒內(nèi)應(yīng)用程序能夠渲染的圖像幀數(shù)量。較高的幀率通常與更流暢的用戶(hù)體驗(yàn)相關(guān)聯(lián)。為什么60 FPS成為了一個(gè)標(biāo)準(zhǔn)呢這是因?yàn)槿搜鄣囊曈X(jué)特性與電子屏幕的刷新頻率有關(guān)。大多數(shù)手機(jī)和計(jì)算機(jī)屏幕的刷新率為60 Hz這意味著它們以每秒60次的頻率刷新屏幕上的內(nèi)容。因此當(dāng)應(yīng)用能夠以60 FPS的速度渲染圖像時(shí)它與屏幕的刷新頻率完美匹配用戶(hù)會(huì)感覺(jué)到非常流暢的體驗(yàn)。如果幀率低于60 FPS用戶(hù)可能會(huì)開(kāi)始感受到卡頓或不流暢的情況因?yàn)閼?yīng)用無(wú)法跟上屏幕的刷新速度導(dǎo)致動(dòng)畫(huà)和交互不夠順暢。因此將60 FPS作為目標(biāo)是為了實(shí)現(xiàn)最佳的用戶(hù)體驗(yàn)。幀率的穩(wěn)定性幀率的穩(wěn)定性表示幀率在一段時(shí)間內(nèi)的波動(dòng)程度。即使幀率的絕對(duì)值較低但如果它非常穩(wěn)定用戶(hù)體驗(yàn)可能會(huì)仍然良好。相反即使幀率的絕對(duì)值很高如果它不穩(wěn)定用戶(hù)可能會(huì)感到不適。不穩(wěn)定的幀率可能表現(xiàn)為畫(huà)面抖動(dòng)或突然的幀率下降這可能讓用戶(hù)感到卡頓。綜合考慮理想的情況是幀率的絕對(duì)值高且穩(wěn)定。然而在某些情況下如果你必須選擇幀率的穩(wěn)定性可能更重要。例如在虛擬現(xiàn)實(shí)VR應(yīng)用中穩(wěn)定的幀率對(duì)于防止暈眩和不適感至關(guān)重要。在普通應(yīng)用中即使幀率的絕對(duì)值不是很高但如果能夠保持穩(wěn)定用戶(hù)也可能感覺(jué)較流暢。如何通過(guò)代碼監(jiān)測(cè)幀率幀率監(jiān)測(cè)通常需要在應(yīng)用的特定部分插入代碼來(lái)捕獲幀率信息。以下是一個(gè)示例使用 Android 的 Choreographer 類(lèi)來(lái)監(jiān)測(cè)幀率publicclassFrameRateMonitor{privatestaticfinal StringTAGFrameRateMonitor;privatestaticfinal longMONITOR_INTERVAL1000;privatestaticlong lastFrameTimeNanos0;privatestaticlong frameCount0;privatestaticlong monitoringStartTime0;privatestaticChoreographer.FrameCallback frameCallback;publicstaticvoidstartMonitoring(){monitoringStartTimeSystemClock.elapsedRealtime();frameCallbacknewChoreographer.FrameCallback(){OverridepublicvoiddoFrame(long frameTimeNanos){long currentFrameTimeNanosframeTimeNanos;if(lastFrameTimeNanos!0){long frameTimeMillis(currentFrameTimeNanos-lastFrameTimeNanos)/1000000;float frameRate1000f/frameTimeMillis;frameCount;long elapsedTimeSystemClock.elapsedRealtime()-monitoringStartTime;if(elapsedTimeMONITOR_INTERVAL){float averageFrameRate(frameCount/(elapsedTime/1000f));Log.d(TAG,Average Frame Rate in the last minute: averageFrameRate FPS);frameCount0;monitoringStartTimeSystemClock.elapsedRealtime();}}lastFrameTimeNanoscurrentFrameTimeNanos;Choreographer.getInstance().postFrameCallback(frameCallback);}};Choreographer.getInstance().postFrameCallback(frameCallback);}publicstaticvoidstopMonitoring(){if(frameCallback!null){Choreographer.getInstance().removeFrameCallback(frameCallback);}lastFrameTimeNanos0;frameCount0;monitoringStartTime0;}}在上面的示例中我們創(chuàng)建了一個(gè)FrameRateMonitor類(lèi)它使用Choreographer來(lái)定期計(jì)算幀率。你可以在應(yīng)用的適當(dāng)位置調(diào)用startMonitoring方法來(lái)啟動(dòng)幀率監(jiān)測(cè)然后在不需要監(jiān)測(cè)時(shí)調(diào)用stopMonitoring方法停止。幀率優(yōu)化技巧一旦你監(jiān)測(cè)到應(yīng)用的幀率問(wèn)題下一步就是優(yōu)化。以下是一些常見(jiàn)的幀率優(yōu)化技巧并附有更詳細(xì)的示例和分析減少視圖層次減少視圖層次是通過(guò)減少視圖的嵌套來(lái)提高幀率的關(guān)鍵方法。視圖的嵌套會(huì)導(dǎo)致繪制操作更加復(fù)雜從而降低幀率。以下是一個(gè)示例不佳的視圖層次結(jié)構(gòu)RelativeLayoutLinearLayoutTextView/ImageView//LinearLayout/RelativeLayout在上述結(jié)構(gòu)中存在多層嵌套導(dǎo)致不必要的繪制。優(yōu)化的方法是減少嵌套如下所示優(yōu)化的視圖層次結(jié)構(gòu)androidx.constraintlayout.widget.ConstraintLayoutTextView/ImageView//androidx.constraintlayout.widget.ConstraintLayout通過(guò)減少嵌套可以減輕繪制負(fù)擔(dān)提高幀率。使用硬件加速Android 提供了硬件加速來(lái)加速圖形渲染。要確保你的應(yīng)用充分利用硬件加速可以通過(guò)在 XML 布局文件中添加android:hardwareAcceleratedtrue或者在代碼中啟用硬件加速。以下是一個(gè)示例application android:hardwareAcceleratedtrue!--應(yīng)用的其他配置--/application啟用硬件加速可以加速視圖的繪制提高幀率。異步任務(wù)將耗時(shí)的任務(wù)放在后臺(tái)線(xiàn)程以避免主線(xiàn)程被阻塞導(dǎo)致幀率下降。這包括網(wǎng)絡(luò)請(qǐng)求、文件讀寫(xiě)、數(shù)據(jù)庫(kù)操作等。以下是一個(gè)示例使用異步任務(wù)處理網(wǎng)絡(luò)請(qǐng)求importandroidx.lifecycle.ViewModelimportandroidx.lifecycle.viewModelScopeimportkotlinx.coroutines.launchclassMyViewModel:ViewModel(){funperformNetworkRequest(){viewModelScope.launch{try{val resultfetchDataFromNetwork()// 處理網(wǎng)絡(luò)請(qǐng)求結(jié)果}catch(e:Exception){// 處理異常}}}privatesuspend funfetchDataFromNetwork():String{// 模擬網(wǎng)絡(luò)請(qǐng)求kotlinx.coroutines.delay(1000)// 延遲1秒模擬網(wǎng)絡(luò)請(qǐng)求耗時(shí)returnNetwork Data}}通過(guò)在后臺(tái)線(xiàn)程執(zhí)行網(wǎng)絡(luò)請(qǐng)求可以防止主線(xiàn)程被阻塞保持幀率穩(wěn)定。圖像和動(dòng)畫(huà)優(yōu)化優(yōu)化應(yīng)用中的圖像和動(dòng)畫(huà)資源非常重要。你應(yīng)該確保圖像是經(jīng)過(guò)壓縮和適當(dāng)縮放的以減小其文件大小。另外使用矢量圖形Vector Drawables可以確保圖標(biāo)在各種屏幕密度下都具有良好的質(zhì)量。以下是一個(gè)示例使用矢量圖形作為圖標(biāo)ImageViewandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:srcdrawable/ic_vector_icon/使用矢量圖形可以減少圖像資源的大小并提高繪制效率。內(nèi)存管理合理管理內(nèi)存對(duì)于維持穩(wěn)定的幀率至關(guān)重要。內(nèi)存泄漏和頻繁的垃圾回收會(huì)導(dǎo)致性能下降。確保在不使用的對(duì)象上及時(shí)釋放引用使用內(nèi)存分析工具來(lái)檢測(cè)潛在的內(nèi)存泄漏。以下是一個(gè)示例手動(dòng)釋放不再需要的對(duì)象引用publicclassMyActivityextendsActivity{privateBitmap largeBitmap;// 需要釋放的對(duì)象OverrideprotectedvoidonCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);// 初始化 largeBitmap}OverrideprotectedvoidonDestroy(){super.onDestroy();// 在銷(xiāo)毀活動(dòng)時(shí)釋放對(duì)象引用if(largeBitmap!null){largeBitmap.recycle();largeBitmapnull;}}}通過(guò)及時(shí)釋放對(duì)象引用可以減少內(nèi)存占用提高幀率。使用 GPU 進(jìn)行繪制盡量使用 GPU 進(jìn)行繪制操作它比 CPU 更高效。可以使用 OpenGL ES 或者 Android的SurfaceView進(jìn)行 GPU 加速繪制。以下是一個(gè)示例使用OpenGL ES渲染圖形publicclassMyGLRendererimplementsGLSurfaceView.Renderer{OverridepublicvoidonSurfaceCreated(GL10gl,EGLConfig config){// 初始化OpenGL環(huán)境}OverridepublicvoidonDrawFrame(GL10gl){// 渲染幀}OverridepublicvoidonSurfaceChanged(GL10gl,int width,height){// 處理視圖大小變化}}通過(guò)使用GPU進(jìn)行繪制可以加速圖形渲染提高幀率。案例場(chǎng)景下面是一些案例場(chǎng)景根據(jù)場(chǎng)景提供分析依據(jù)讓大家更清楚的理解問(wèn)題的解決思路。掉幀率過(guò)高幀率監(jiān)測(cè)數(shù)據(jù)顯示掉幀率從平均的 60 FPS 下降到 20 FPS導(dǎo)致用戶(hù)在應(yīng)用中感受到卡頓。CPU 使用率數(shù)據(jù)顯示在特定時(shí)間點(diǎn)主線(xiàn)程的 CPU 使用率達(dá)到 90%表明高 CPU 負(fù)載與卡頓相關(guān)。內(nèi)存使用情況數(shù)據(jù)顯示內(nèi)存占用不斷增加暗示可能存在內(nèi)存泄漏。卡頓發(fā)生在網(wǎng)絡(luò)請(qǐng)求時(shí)幀率監(jiān)測(cè)數(shù)據(jù)清晰地顯示卡頓問(wèn)題發(fā)生在用戶(hù)進(jìn)行網(wǎng)絡(luò)請(qǐng)求的時(shí)候幀率從 60 FPS 下降到 10 FPS。CPU 使用率數(shù)據(jù)表明在網(wǎng)絡(luò)請(qǐng)求期間主線(xiàn)程的 CPU 使用率迅速上升至 100%。響應(yīng)時(shí)間數(shù)據(jù)顯示網(wǎng)絡(luò)請(qǐng)求的響應(yīng)時(shí)間長(zhǎng)達(dá) 5 秒以上進(jìn)一步印證了網(wǎng)絡(luò)請(qǐng)求問(wèn)題。內(nèi)存泄漏導(dǎo)致性能下降內(nèi)存分析工具的報(bào)告清楚地顯示了應(yīng)用中存在內(nèi)存泄漏問(wèn)題標(biāo)識(shí)出了具體的對(duì)象和引用鏈。幀率監(jiān)測(cè)數(shù)據(jù)顯示隨著內(nèi)存占用的不斷增加幀率逐漸下降最終導(dǎo)致用戶(hù)體驗(yàn)不佳。GPU 使用率高GPU 使用率監(jiān)測(cè)數(shù)據(jù)表明 GPU 使用率在圖形渲染時(shí)持續(xù)高達(dá) 90%導(dǎo)致幀率波動(dòng)明顯。渲染時(shí)間分布數(shù)據(jù)清晰地展示了部分幀的渲染時(shí)間明顯較長(zhǎng)與高 GPU 使用率相關(guān)。電池消耗過(guò)高電池消耗監(jiān)測(cè)數(shù)據(jù)顯示應(yīng)用在后臺(tái)運(yùn)行時(shí)持續(xù)占用大量電池導(dǎo)致設(shè)備續(xù)航時(shí)間大幅減少。后臺(tái)任務(wù)執(zhí)行頻率數(shù)據(jù)明確展示了部分后臺(tái)任務(wù)過(guò)于頻繁執(zhí)行消耗了大量電池。結(jié)論幀率監(jiān)測(cè)和優(yōu)化是Android應(yīng)用性能提升的關(guān)鍵步驟。通過(guò)使用合適的工具你可以更好地了解應(yīng)用的幀率表現(xiàn)識(shí)別性能問(wèn)題并采取措施來(lái)改善用戶(hù)體驗(yàn)。幀率優(yōu)化需要持續(xù)的努力不斷關(guān)注幀率并采取適當(dāng)?shù)拇胧└鶕?jù)應(yīng)用性質(zhì)選擇適當(dāng)?shù)膸史秶詫?shí)現(xiàn)最佳用戶(hù)體驗(yàn)。幀率的絕對(duì)值和穩(wěn)定性都對(duì)于用戶(hù)體驗(yàn)至關(guān)重要應(yīng)該綜合考慮并追求平衡。最后大家分享一份全套的Android學(xué)習(xí)資料給那些想學(xué)習(xí) Android 的小伙伴們一點(diǎn)幫助適用于任何想學(xué)習(xí)Android開(kāi)發(fā)但不知道從哪里開(kāi)始的人也適用于已經(jīng)開(kāi)始進(jìn)行Android開(kāi)發(fā)但想要變得更好的任何人一、Android所有方向的學(xué)習(xí)路線(xiàn)為了成為更好的 Android 開(kāi)發(fā)者這里為大家提供了總的路線(xiàn)圖。它的用處就在于你可以按照上面的知識(shí)點(diǎn)去找對(duì)應(yīng)的學(xué)習(xí)資源保證自己學(xué)得較為全面。如果下面這個(gè)學(xué)習(xí)路線(xiàn)能幫助大家成為一個(gè)更好的 Android 開(kāi)發(fā)者那么我的使命也就完成了包括Android應(yīng)用開(kāi)發(fā)、系統(tǒng)開(kāi)發(fā)、音視頻開(kāi)發(fā)、Flutter開(kāi)發(fā)、小程序開(kāi)發(fā)、UI界面、車(chē)載系統(tǒng)開(kāi)發(fā)等等二、學(xué)習(xí)軟件工欲善其事必先利其器。學(xué)習(xí)Android常用的Android Studio視頻教程和Android Studio最新的安裝包都在這里了給大家節(jié)省了很多時(shí)間。三、進(jìn)階學(xué)習(xí)視頻我們?cè)趯W(xué)習(xí)的時(shí)候往往書(shū)籍源碼難以理解閱讀困難這時(shí)候視頻教程教程是就很適合了生動(dòng)形象加上案例實(shí)戰(zhàn)科學(xué)有趣才能更方便的學(xué)習(xí)下去。四、實(shí)戰(zhàn)案例光學(xué)理論是沒(méi)用的要學(xué)會(huì)跟著一起敲要?jiǎng)邮謱?shí)操才能將自己的所學(xué)運(yùn)用到實(shí)際當(dāng)中去這時(shí)候可以搞點(diǎn)實(shí)戰(zhàn)案例來(lái)學(xué)習(xí)。五、經(jīng)典書(shū)籍閱讀閱讀Android經(jīng)典書(shū)籍可以幫助讀者提高技術(shù)水平開(kāi)拓視野掌握核心技術(shù)提高解決問(wèn)題的能力同時(shí)也可以借鑒他人的經(jīng)驗(yàn)。對(duì)于想要深入學(xué)習(xí)Android開(kāi)發(fā)的讀者來(lái)說(shuō)閱讀Android經(jīng)典書(shū)籍是非常有必要的。六、面試資料我們學(xué)習(xí)Android必然是為了找到高薪的工作下面這些面試題是來(lái)自阿里、騰訊、字節(jié)等一線(xiàn)互聯(lián)網(wǎng)大廠(chǎng)最新的面試資料并且有阿里大佬給出了權(quán)威的解答刷完這一套面試資料相信大家都能找到滿(mǎn)意的工作。這份完整版的Android全套學(xué)習(xí)資料已經(jīng)上傳CSDN朋友們?nèi)绻枰梢晕⑿艗呙柘路紺SDN官方認(rèn)證二維碼免費(fèi)領(lǐng)取【保證100%免費(fèi)】