1. android流暢度評估及卡頓優化
Google定義:界面呈現是指從應用生成幀並將其顯示在屏幕上的動作。要確保用戶能夠流暢地與應用互動,應用呈現每幀的時間不應超過16ms,以達到每秒60幀的呈現速度(為什麼是60fps?)。
如果應用存在界面呈現緩慢的問題,系統會不得不跳過一些幀,這會導致用戶感覺應用不流暢,我們將這種情況稱為卡頓。
來源於: Google Android的為什麼是60fps?
16ms意味著1000/60hz,相當於60fps。這是因為人眼與大腦之間的協作無法感知超過60fps的畫面更新。12fps大概類似手動快速翻動書籍的幀率, 這明顯是可以感知到不夠順滑的。24fps使得人眼感知的是連續線性的運動,這其實是歸功於運動模糊的效果。 24fps是電影膠圈通常使用的幀率,因為這個幀率已經足夠支撐大部分電影畫面需要表達的內容,同時能夠最大的減少費用支出。 但是低於30fps是 無法順暢表現絢麗的畫面內容的,此時就需要用到60fps來達到想要的效果,超過60fps就沒有必要了。如果我們的應用沒有在16ms內完成屏幕刷新的全部邏輯操作,就會發生卡頓。
首先要了解Android顯示1幀圖像,所經歷的完整過程。
如圖所示,屏幕顯示1幀圖像需要經歷5個步驟:
常見的丟幀情況: 渲染期間可能出現的情況,渲染大於16ms和小於16ms的情況:
上圖中應該繪制 4 幀數據 , 但是實際上只繪制了 3 幀 , 實際幀率少了一幀
判斷APP是否出現卡頓,我們從通用應用和游戲兩個緯度的代表公司標准來看,即Google的Android vitals性能指標和地球第一游戲大廠騰訊的PrefDog性能指標。
以Google Vitals的卡頓描述為准,即呈現速度緩慢和幀凍結兩個維度判斷:
PerfDog Jank計算方法:
幀率FPS高並不能反映流暢或不卡頓。比如:FPS為50幀,前200ms渲染一幀,後800ms渲染49幀,雖然幀率50,但依然覺得非常卡頓。同時幀率FPS低,並不代表卡頓,比如無卡頓時均勻FPS為15幀。所以平均幀率FPS與卡頓無任何直接關系)
當了解卡頓的標准以及渲染原理之後,可以得出結論,只有丟幀情況才能准確判斷是否卡頓。
mpsys 是一種在設備上運行並轉儲需要關注的系統服務狀態信息的 Android 工具。通過向 mpsys 傳遞 gfxinfo 命令,可以提供 logcat 格式的輸出,其中包含與錄制階段發生的動畫幀相關的性能信息。
藉助 Android 6.0(API 級別 23),該命令可將在整個進程生命周期中收集的幀數據的聚合分析輸出到 logcat。例如:
這些總體統計信息可以得到期間的FPS、Jank比例、各類渲染異常數量統計。
命令 adb shell mpsys gfxinfo <PACKAGE_NAME> framestats 可提供最近120個幀中,渲染各階段帶有納秒時間戳的幀時間信息。
關鍵參數說明:
通過gfxinfo輸出的幀信息,通過定時reset和列印幀信息,可以得到FPS(幀數/列印間隔時間)、丟幀比例((janky_frames / total_frames_rendered)*100 %)、是否有幀凍結(幀耗時>700ms)。
根據第2部分的通用應用卡頓標准,可以通過丟幀比例和幀凍結數量,准確判斷當前場景是否卡頓。並且通過定時截圖,還可以根據截圖定位卡頓的具體場景。
如上圖所示,利用gfxinfo開發的檢查卡頓的小工具,圖中參數和卡頓說明如下:
根據上面對gfxinfo的幀信息解析,可以准確計算出每一幀的耗時。從而可以開發出滿足騰訊PerfDog中關於普通卡頓和嚴重卡頓的判斷。
依賴定時截圖,即可准確定位卡頓場景。如下圖所示(此處以PerfDog截圖示例):
通過第3部分的卡頓評估方法,我們可以定位到卡頓場景,但是如何定位到具體卡頓原因呢。
首先了解卡頓問題定位工具,然後再了解常見的卡頓原因,即可通過復現卡頓場景的同時,用工具去定位具體卡頓問題。
重點就是,充分利用gfxinfo輸出的幀信息,對卡頓問題進行分類。
了解了高效定位卡頓的方法和卡頓問題定位工具,再熟悉一下常見的卡頓原因,可以更熟練的定位和優化卡頓。
SurfaceFlinger 負責 Surface 的合成,一旦 SurfaceFlinger 主線程調用超時,就會產生掉幀。
SurfaceFlinger 主線程耗時會也會導致 hwc service 和 crtc 不能及時完成,也會阻塞應用的 binder 調用,如 dequeueBuffer、queueBuffer 等。
後台進程活動太多,會導致系統非常繁忙,cpu io memory 等資源都會被佔用,這時候很容易出現卡頓問題,這也是系統這邊經常會碰到的問題。
mpsys cpuinfo 可以查看一段時間內 cpu 的使用情況:
當線程為 Runnable 狀態的時候,調度器如果遲遲不能對齊進行調度,那麼就會產生長時間的 Runnable 線程狀態,導致錯過 Vsync 而產生流暢性問題。
system_server 的 AMS 鎖和 WMS 鎖 , 在系統異常的情況下 , 會變得非常嚴重 , 如下圖所示 , 許多系統的關鍵任務都被阻塞 , 等待鎖的釋放 , 這時候如果有 App 發來的 Binder 請求帶鎖 , 那麼也會進入等待狀態 , 這時候 App 就會產生性能問題 ; 如果此時做 Window 動畫 , 那麼 system_server 的這些鎖也會導致窗口動畫卡頓。
Android P 修改了 Layer 的計算方法 , 把這部分放到了 SurfaceFlinger 主線程去執行, 如果後台 Layer 過多,就會導致 SurfaceFlinger 在執行 rebuildLayerStacks 的時候耗時 , 導致 SurfaceFlinger 主線程執行時間過長。
主線程執行 Input Animation Measure Layout Draw decodeBitmap 等操作超時都會導致卡頓 。
Activity resume 的時候, 與 AMS 通信要持有 AMS 鎖, 這時候如果碰到後台比較繁忙的時候, 等鎖操作就會比較耗時, 導致部分場景因為這個卡頓, 比如多任務手勢操作。
應用裡面涉及到 WebView 的時候, 如果頁面比較復雜, WebView 的性能就會比較差, 從而造成卡頓。
如果屏幕幀率和系統的 fps 不相符 , 那麼有可能會導致畫面不是那麼順暢. 比如使用 90 Hz 的屏幕搭配 60 fps 的動畫。
由上面的分析可知對象分配、垃圾回收(GC)、線程調度以及Binder調用 是Android系統中常見的卡頓原因,因此卡頓優化主要以下幾種方法,更多的要結合具體的應用來進行:
在計算機和通信領域,幀是一個包括「幀同步串列」的數字數據傳輸單元或數字數據包。
在視頻領域,電影、電視、數字視頻等可視為隨時間連續變換的許多張畫面,其中幀是指每一張畫面。
2. androidUI卡頓原理分析及Vsync信號機制
一、UI卡頓定義
1、用戶角度:app操作界面刷新緩慢,響應不及時;界面滑動不夠流暢;
2、系統角度:屏幕刷新幀率不穩定,掉幀嚴重,無法保證每秒60幀,導致屏幕畫面撕裂;
二、UI卡頓常見原因分析以及處理方案
1、過度繪制:
原因:界面布局設計不合理或者過於復雜導致系統無法在16毫秒內完成渲染,view過度繪制導致CPU或者GPU負載過重,View頻繁觸發measure、layout操作,導致measure、layout累計耗時嚴重以及整個View錯誤的頻繁重新渲染;
方案:優化界面布局,使界面布局視圖扁平化,去除不必要的背景顏色,減少透明色的使用;
方案依據原理:盡量減少View在系統中measure、layout、draw的累計時間;
2、UI線程的復雜運算
原因:UI主線程運算耗時
方案:減少UI線程中數據運算,使用子線程處理耗時任務
3、頻繁GC
原因:(1)、內存抖動;(2)、瞬間產生大量對象,消耗內存;
方案:盡量避免在循環邏輯或者onDraw方法中頻繁創建新對象和使用局部變數;
三、android Vsync機制
1、什麼是Vsync ?
Vsync 是Vertical Synchronization(垂直同步)的縮寫,是一種在PC上很早就廣泛使用的技術,可以簡單的把它認為是一種定時中斷。而在Android 4.1(JB)中已經開始引入VSync機制,用來同步渲染,讓AppUI和SurfaceFlinger可以按硬體產生的VSync節奏進行工作。
2、Android屏幕刷新過程
Android系統每隔16ms發出VSYNC信號,觸發對UI進行渲染,屏幕的刷新過程是每一行從左到右(行刷新,水平刷新,Horizontal Scanning),從上到下(屏幕刷新,垂直刷新,Vertical Scanning)。當整個屏幕刷新完畢,即一個垂直刷新周期完成,會有短暫的空白期,此時發出 VSync 信號。所以,VSync 中的 V 指的是垂直刷新中的垂直-Vertical。
3、沒有使用Vsync的情況
可見vsync信號沒有提醒CPU/GPU工作的情況下,在第一個16ms之內,一切正常。然而在第二個16ms之內,幾乎是在時間段的最後CPU才計算出了數據,交給了Graphics Driver,導致GPU也是在第二段的末尾時間才進行了繪制,整個動作延後到了第三段內。從而影響了下一個畫面的繪制。這時會出現Jank(閃爍,可以理解為卡頓或者停頓)。這時候CPU和GPU可能被其他操作佔用了,這就是卡頓出現的原因;
4、使用Vsync同步
CPU/GPU接收vsync信號,Vsync每16ms一次,那麼在每次發出Vsync命令時,CPU都會進行刷新的操作。也就是在每個16ms的第一時間,CPU就會響應Vsync的命令,來進行數據刷新的動作。CPU和GPU的刷新時間,和Display的FPS是一致的。因為只有到發出Vsync命令的時候,CPU和GPU才會進行刷新或顯示的動作。CPU/GPU接收vsync信號提前准備下一幀要顯示的內容,所以能夠及時准備好每一幀的數據,保證畫面的流暢;
5、多級緩沖
Android除了使用Vsync機制,還使用了多級緩沖的策略來優化屏幕顯示,如雙重緩沖(A + B),當Display buffer A 數據時,CPU/GPU就已經在buffer B 中處理下一幀要顯示的數據了。
可是,當系統資源緊張性能降低時,導致GPU在處理某幀數據時太耗時,在Vsync信號到來時,buffer B的數據還沒准備好,此時不得不顯示buffer A的數據,這樣導致後面CPU/GPU沒有新的buffer准備數據,空白時間無事可做,後面Jank頻出
因此採用三級緩沖來解決系統對性能不穩定導致的卡頓
當出現上面所述情況後,新增一個buffer C 可以減少CPU和GPU在Vsync同步間的空白間隙,此時CPU/GPU能夠利用buffer C 繼續工作,後面buffer A 和 buffer B 依次處理下一幀數據。這樣僅是產生了一個Jank,可以忽略不計,以後的流程就順暢了。
註:在多數正常情況下還是使用二級緩沖機制,三級緩沖只是在需要的時候才使用;
3. 知識體系四:Android動畫工作原理
1.Android 動畫的工作原理?
在android系統中動畫分為兩種分別是幀動畫和屬性動畫。對於動畫的工作原理主要涉及到的是幀動畫的實現。
幀動畫主要有旋轉RotatleAnimation,縮放ScaleAnimation,透明AlphaAnimation,平移TranslateAnimation等都是Animation的子類。Animation控制動畫的效果,Transformation 對動畫進行計算。
對於動畫的原理簡單說就是從一個動畫的啟動狀態,到動畫結束狀態,和動畫持續總時間,在這段時間中任一時間點動畫的狀態計算和顯示的過程。
計算 :是通過Animation的getTransformation()方法首先對時間進行歸一化時間讓時間在0~1之間,進行計算。滿足條件之後就會調用applyTransformation()方法處理實現動畫類型的計算。當前時間點的轉換狀態保存到Transformation 的Matrix中等待顯示的時候使用。
顯示 :動畫顯示工作主要依賴於Choreograther類,此類是線程唯一的,Choreograther和Handler用法類似,都是通過post一個Runnable對象到隊列中等待VSYSC屏幕垂直同步信號刷新(16ms)刷新一次,然後觸發ViewRootImpl的view的遍歷工作,回調到view.draw()方法時就會把之前applyTransformation 計算的此時刻的Transformation 的Matrix賦值到Canvas上, 這也就是為什麼我們使用幀動畫時候我們的view的屬性並沒有改變,這就是根源因為計算得到的Matrix被Canvas使用了,並沒有直接賦值到我們的view上。 對於屬性動畫來說主要使用animator實現看下面解析:
2.Animation 和 Animator 的區別?
Animation和Animator都是抽象類,都有子類,Animation通過Transformation對動畫進行Matrix轉換來作用到Canvas上實現動畫效果。而Animator只是一個工具類,主要是用來控制在一段時間內某一個值的變化過程,然後我們再根據這個值來作用到view的屬性上,以此來實現動畫效果。為了讓這個變化的過程能達到加速減速等變化效果系統提供了插值器Interpolator。他們的實現思想都是一致的。
3.幀動畫 和 屬性動畫的區別?
4. Android 繪制與 16ms 不得不說的故事
刷新率:每秒屏幕刷新次數。
幀率:GPU 在一秒內繪制的幀數。
雖然現在有的廠商推出了高刷新率的手機,但是主流的還是 60Hz,即1秒顯示60幀,1000ms / 60 frames ≈ 16.67 ms/frames,為了保證 App 的流暢度,我們應該盡量讓每幀的繪制時間不超過 16ms。
Android 的顯示過程可以簡單概括為:應用程序把經過 measure(測量)、layout(布局)、draw(繪制)後的 surface 緩存數據,通過 SurfaceFlinger 把數據渲染到顯示屏幕上,通過 Android 的刷新機制來刷新數據。換言之,應用層負責繪制,系統層負責渲染,通過進程間通信把應用層需要繪制的數據傳遞到系統層服務,系統層通過刷新機制把數據更新到屏幕上。
以下是有關概念的解釋:
在 Android 中每個 view 都會經過 measure 和 layout 來確定其所在的大小和位置,然後繪制到 surface (緩沖區上),繪制是由 ViewRootImpl 類中 performTraversals() 方法發起的。
Android支持兩種繪制方式: 和 。硬體極速從 Android 3.0 開始支持,它在 UI 顯示和繪制效率方面遠高於軟體繪制,但是它的也有缺點:
經過多次繪制後,要顯示的 view 相關的數據存儲(如大小和位置)在 Surface 的緩沖區中,接下來渲染操作交由系統進程中的 SurfaceFlinger 服務來完成,這是一個 IPC(進程間通信)過程。SurfaceFlinger 的主要工作流程如下:
當 Android 應用層在圖形緩沖區中繪制好 View 層次結後,應用層通過 Binder 機制與 SurfaceFlinger 通信並藉助一塊匿名共享內存把圖形緩沖區交給 SurfaceFlinger 服務。由於單純的匿名共享服務在傳遞多個窗口數據時缺乏有效的管理,所以匿名共享內存就被抽象為一個更上層的數據結構——SharedClient,在 SharedClient 中,最多有 31 個 SharedBufferStack,每個 SharedBufferStack 都對應一個 Surface 即一個 Window。 這表明一個 Android 應用程序最多可以包含 31 個 window 。
繪制的過程首先是 CPU 准備數據(measure、layout等),GPU 負責柵格化、渲染。因為圖像 API 不允許 CPU 直接與 GPU 通信,所以要通過一個圖形驅動的中間層來進行連接。圖形驅動裡面維護了一個隊列,CPU 把 display list(待顯示的數據列表)添加到隊列中,GPU 從這個隊列中取出數據進行繪制,最終在屏幕上顯示出來,如下圖所示:
Android 系統每隔 16ms 會發出 VSYNC 信號,觸發對 UI 進行渲染,如果每次都渲染成功,就能夠達到流暢畫面所需的 60PS。
雙緩沖顧名思義是有兩個緩沖區(上文提到的 SharedBufferStack),分別是 FontBuffer(又叫作 FrameBuffer) 和 BackBuffer。UI 總是先在 Back Buffer 中繪制,然後再和 Font Buffer 交換,渲染到顯示設備中,即只有當另一個 buffer 的數據准備好後,才會通過系統調用來通知顯示設備切換 Buffer。
雙緩沖機制在大部分情況下是適用的,但是如果某個環節出現了問題,CPU 資源就有可能存在浪費,如下圖所示:
VSYNC 類似與時鍾中斷。豎線分割的部分代表 16ms 的時間段。正常情況下,在每一時間段內,Display 顯示一幀數據(即每秒60幀)。
上圖中在第二個 16ms 時間段內,Display 本應顯示 B 幀,但是因為 GPU 還在處理 B 幀,導致 A 幀被重復顯示。與此同時,在第二個時間段內,處於 CPU 處於空閑狀態,造成了浪費。因為 A Buffer 被 Diaplay 在使用(SufaceFlinger 用完後不會釋放當前的 Buffer,只會釋放舊的 Buffer),B Buffer 被 GPU 在使用,這就是 雙緩沖機制的局限性。
Android 4.1 版本中對 Android Display 系統進行了重構,引入了三個核心元素:
在第二個 16ms 時間內,CPU 使用 C Buffer 繪圖,雖然還是會多顯示 A 幀一次,但是後續的顯示相對雙緩沖機制就順滑多了。但是 Buffer 並不是越多越好,從上圖可知,在第二個時間內,CPU 繪制的第 C 幀數據要到第四個 16ms 才能顯示,這比雙 Buffer 多了 16ms 的延遲。由此可見,雙緩沖保證低時延,三緩沖保證穩定性。
整個流程簡單來說就是 CPU/GPU 會接收到 VSYNC 信號,觸發對 UI 進行渲染(每 16ms 顯示一幀)。 在 16ms 內需要完成兩項任務:將 UI 對象轉換為一系列多邊形和紋理(柵格化)和 CPU 傳遞處理數據到 GPU ,更詳細的內容可以看這篇文章 Android的16ms和垂直同步以及三重緩存 。
了解 Android 繪制流程後,我們不難反推 Android 應用程序卡頓的原因:
5. Android UI卡頓原因及解決辦法
渲染機制介紹
為了分析UI卡頓,我們有必要理解一下渲染機制,這套渲染機制適用於絕大部分的屏幕渲染,其中包括Android手機等眾多屏幕設備。
渲染的一些重要參數:
屏幕刷新理想的頻率(硬體的角度):60Hz
理想的一秒內繪制的幀數,幀率(屏幕刷新的角度):60fps
這兩個參數都是理想值,指代的都是同一個概念。實際情況中難免會比它們低。在60fps內,系統會得到發送的VSYNC(垂直刷新/繪制)信號去進行渲染,就會正常地繪制出我們需要的圖形界面。Android手機進行繪制的時候,GPU幫助我們將UI組件等計算成紋理Texture和三維圖形Polygons,同時會使用OpenGL---會將紋理和Polygons緩存在GPU內存裡面。
其中,VSYNC:有兩個概念
Refresh Rate:屏幕在一秒時間內刷新屏幕的次數----有硬體的參數決定,比如60HZ,即屏幕每秒刷新60次
Frame Rate:GPU在一秒內繪制操作的幀數,比如:60fps,
基本結論
要達到60fps,就要求:每一幀只能停留16ms。(大概就是1000ms/60 ~= 16ms刷新一次)
內存抖動是因為大量的對象被創建又在短時間內馬上被釋放。
瞬間產生大量的對象會嚴重佔用Young Generation的內存區域,當達到閥值,剩餘空間不夠的時候,也會觸發GC。即使每次分配的對象佔用了很少的內存,但是他們疊加在一起會增加Heap的壓力,從而觸發更多其他類型的GC。這個操作有可能會影響到幀率,並使得用戶感知到性能問題。
Android裡面是一個三級Generation的內存模型,最近分配的對象會存放在Young Generation區域,當這個對象在這個區域停留的時間達到一定程度,它會被移動到Old Generation,最後到Permanent Generation區域。
Android每個16ms就會繪制一次Activity,通過上述的結論我們知道,如果由於一些原因導致了我們的邏輯、CPU耗時、GPU耗時大於16ms( 應用卡頓的根源就在於16ms內不能完成繪制渲染合成過程,16ms需要完成視圖樹的所有測量、布局、繪制渲染及合成 ),UI就無法完成一次繪制,那麼就會造成卡頓。
比如說,在16ms內,發生了頻繁的GC:
在第一個16ms內,UI正常地完成了繪制,那麼屏幕不會卡頓。
在第二個16ms內,由於某些原因觸發了頻發的GC,UI無法在16ms內完成繪制,就會卡頓。
UI卡頓外部和內部常見原因
下面總結一些常見的UI卡頓原因:
1.內存抖動的問題
2.方法太耗時了(CPU佔用)
1) CPU計算時間,CPU的測量、布局時間
2)CPU將計算好的Polygons和Texture傳遞到GPU的時候也需要時間。OpenGL ES API允許數據上傳到GPU後可以對數據進行保存,緩存到display list。因此,我們平移等操作一個view是幾乎不怎麼耗時的 。
3) GPU進行格柵化
當我們的布局是用的FrameLayout的時候,我們可以把它改成merge,可以避免自己的幀布局和系統的ContentFrameLayout幀布局重疊造成重復計算(measure和layout)。
使用ViewStub:當載入的時候才會佔用。不載入的時候就是隱藏的,僅僅佔用位置。
CPU優化建議
針對CPU的優化,從減輕加工View對象成Polygons和Texture來下手:
View Hierarchy中包涵了太多的沒有用的view,這些view根本就不會顯示在屏幕上面,一旦觸發測量和布局操作,就會拖累應用的性能表現。那麼我們就需要利用工具進行分析。
如何找出裡面沒用的view呢?或者減少不必要的view嵌套。
我們利用工具:Hierarchy Viewer進行檢測,優化思想是:查看自己的布局,層次是否很深以及渲染比較耗時,然後想辦法能否減少層級以及優化每一個View的渲染時間。
我們打開APP,然後打開Android Device Monitor,然後切換到Hierarchy Viewer面板。除了看層次結構之外,還可以看到一些耗時的信息:
三個圓點分別代表:測量、布局、繪制三個階段的性能表現。
1)綠色:渲染的管道階段,這個視圖的渲染速度快於至少一半的其他的視圖。
2)黃色:渲染速度比較慢的50%。
3)紅色:渲染速度非常慢。
GPU優化建議就是一句話:盡量避免過度繪制(overdraw)
一、背景經常容易造成過度繪制。
手機開發者選項裡面找到工具:Debug GPU overdraw,其中,不同顏色代表了繪制了幾次:
6. 針對Android的性能優化集中哪些方面
一、概要:
本文主要以Android的渲染機制、UI優化、多線程的處理、緩存處理、電量優化以及代碼規范等幾方面來簡述Android的性能優化
二、渲染機制的優化:
大多數用戶感知到的卡頓等性能問題的最主要根源都是因為渲染性能。
Android系統每隔16ms發出VSYNC信號,觸發對UI進行渲染, 如果每次渲染都成功,這樣就能夠達到流暢的畫面所需要的60fps,為了能夠實現60fps,這意味著程序的大多數操作都必須在16ms內完成。
*關於JobScheler的更多知識可以參考http://hukai.me/android-training-course-in-chinese/background-jobs/scheling/index.html
七、代碼規范
1)for loop中不要聲明臨時變數,不到萬不得已不要在裡面寫try catch。
2)明白垃圾回收機制,避免頻繁GC,內存泄漏,OOM(有機會專門說)
3)合理使用數據類型,StringBuilder代替String,少用枚舉enum,少用父類聲明(List,Map)
4)如果你有頻繁的new線程,那最好通過線程池去execute它們,減少線程創建開銷。
5)你要知道單例的好處,並正確的使用它。
6)多用常量,少用顯式的"action_key",並維護一個常量類,別重復聲明這些常量。
7)如果可以,至少要弄懂設計模式中的策略模式,組合模式,裝飾模式,工廠模式,觀察者模式,這些能幫助你合理的解耦,即使需求頻繁變更,你也不用害怕牽一發而動全身。需求變更不可怕,可怕的是沒有在寫代碼之前做合理的設計。
8)View中設置緩存屬性.setDrawingCache為true.
9)cursor的使用。不過要注意管理好cursor,不要每次打開關閉cursor.因為打開關閉Cursor非常耗時。Cursor.require用於刷cursor.
10)採用SurfaceView在子線程刷新UI,避免手勢的處理和繪制在同一UI線程(普通View都這樣做)
11)採用JNI,將耗時間的處理放到c/c++層來處理
12)有些能用文件操作的,盡量採用文件操作,文件操作的速度比資料庫的操作要快10倍左右
13)懶載入和緩存機制。訪問網路的耗時操作啟動一個新線程來做,而不要再UI線程來做
14)如果方法用不到成員變數,可以把方法申明為static,性能會提高到15%到20%
15)避免使用getter/setter存取field,可以把field申明為public,直接訪問
16)私有內部類要訪問外部類的field或方法時,其成員變數不要用private,因為在編譯時會生成setter/getter,影響性能。可以把外部類的field或方法聲明為包訪問許可權
17)合理利用浮點數,浮點數比整型慢兩倍
18)針對ListView的性能優化,ListView的背景色與cacheColorHint設置相同顏色,可以提高滑動時的渲染性能。ListView中getView是性能是關鍵,這里要盡可能的優化。
getView方法中要重用view;getView方法中不能做復雜的邏輯計算,特別是資料庫操作,否則會嚴重影響滑動時的性能
19)不用new關鍵詞創建類的實例,用new關鍵詞創建類的實例時,構造函數鏈中的所有構造函數都會被自動調用。但如果一個對象實現了Cloneable介面,我們可以調用它的clone()方法。
clone()方法不會調用任何類構造函數。在使用設計模式(Design Pattern)的場合,如果用Factory模式創建對象,則改用clone()方法創建新的對象實例非常簡單。例如,下面是Factory模式的一個典型實現:
20)public static Credit getNewCredit() {
return new Credit();
}
改進後的代碼使用clone()方法,如下所示:
private static Credit BaseCredit = new Credit();
public static Credit getNewCredit() {
return (Credit) BaseCredit.clone();
}
上面的思路對於數組處理同樣很有用。
21)乘法和除法
考慮下面的代碼:
for (val = 0; val < 100000; val +=5) { alterX = val * 8; myResult = val * 2; }
用移位操作替代乘法操作可以極大地提高性能。下面是修改後的代碼:
for (val = 0; val < 100000; val += 5) { alterX = val << 3; myResult = val << 1; }
22)ViewPager同時緩存page數最好為最小值3,如果過多,那麼第一次顯示時,ViewPager所初始化的pager就會很多,這樣pager累積渲染耗時就會增多,看起來就卡。
23)每個pager應該只在顯示時才載入網路或資料庫(UserVisibleHint=true),最好不要預載入數據,以免造成浪費
24)提高下載速度:要控制好同時下載的最大任務數,同時給InputStream再包一層緩沖流會更快(如BufferedInputStream)
25)提供載入速度:讓服務端提供不同解析度的圖片才是最好的解決方案。還有合理使用內存緩存,使用開源的框架
引用:Android性能優化的淺談
7. 如何測量Android應用的幀率FPS
通過 [設置]->[開發者選項]->[GPU呈現模式分析] ->[在屏幕上顯示為條形圖] 進行直觀的取樣,截圖如下:
繪制過程中的不同顏色具有不同的含義,詳細解釋請移步>> 官網查看更多。
那麼是不是說我只需要打開界面去數一下超過綠色閾值的柱狀圖有多少就可以觀察我們應用的流暢度了?然而並沒有,因為這個方式獲取到的渲染時間只是UI主線程上的繪制行為,目前我所接手的項目,採用的方式是捕捉相機的數據然後放到GPU中去進行繪制,有單獨的繪制線程,單獨的視圖,所以這個方案並不適合我手上的項目。