Android應用怎樣才能如絲般順滑

  • 2019 年 10 月 28 日
  • 筆記

背景

現在醫美行業競爭激烈,產品打入市場直接可獲客的就是用戶的體驗度,這個體驗度除了有完善的功能外,更重要的還有界面UI的操作流暢度,流暢度的好壞,對一個產品的體驗和口碑有着極大的影響,當年Android 手機經常被人詬病的一點就是流暢度遠遠比不上iPhone,即使到現在,這個影響也依然存在。

為了提高流暢度,其實Google對android系統也進行了大量的優化:

1、使用GPU進行硬件加速;

2、引入VSync機制;

3、把Dalvik換成art;

…….

流暢度評測指標FPS—>SM

對於流暢度的評測,大家第一時間會想到FPS。當前業界衡量一個APP是否流暢的主要指標就是FPS。但是有經驗的同學會發現使用FPS測試APP的流暢度,會存在測試數據和實際感官不一致的問題,比如有時候FPS很低,但是APP看起來確實很流暢。

舉個例子:

操作淘寶APP的首頁,進行頁面的滑動,實際感官很順暢。讓我們來看看FPS的值吧。

從圖表中的數據我們可以看到:

1)為什麼FPS很低,但是我們不覺得APP卡頓?

2)APP停止操作之後,FPS還是一直在變化,這樣的情況是否會影響到FPS的準確度?

出現這種現象原因是什麼呢?基於這兩個問題 我們分析一下FPS的原理:

FPS的原理:

1、手機屏幕顯示的內容是通過Android系統的SurfaceFLinger類,把當前系統里所有進程需要顯示的信息合成一幀,然後提交到屏幕進行顯示。

2、1s內SurfaceFLinger提交到屏幕的幀數。

根據這個原理就可以解釋上面的問題了:

1)如果APP在1S內只有30幀的顯示需求,比如畫一個動畫只畫了0.5s就畫完了,那麼FPS最高也就只有30幀/秒,並不能代表APP是卡頓的。另外如果屏幕根本沒有繪製需求,畫面是靜止的,那FPS就是0。

2)屏幕上顯示的每一幀合成都是針對手機里的所有進程的,所以即使APP停止了繪製,手機里其他的進程可能還在繪製。

通過上面的分析我們得出:FPS來作為流暢度的指標是不準確的,那流暢度的指標用什麼來描述更為準確呢?別急,鵝廠自主研發的性能工具–GT可以幫助我們準確的檢測一個APP的流暢度。

小貼士

GT(隨身調)是APP的隨身調測平台,它是直接運行在手機上的「集成調測環境」(IDTE, Integrated Debug Environment)。利用GT,僅憑一部手機,無需連接電腦,您即可對APP進行快速的性能測試(CPU、內存、流量、電量、幀率/流暢度等等)、開發日誌的查看、Crash日誌查看、網絡數據包的抓取、APP內部參數的調試、真機代碼耗時統計等。

GT工具中的SM(SMoothness)指標給出來一個衡量流暢度好壞的標準,如下圖:

可能有人會有疑問:如果出現了SM值<=50的情況,我們要怎麼辦呢?或者我們拿這個SM的值去衡量一個APP的流暢度,開發同事是否認可呢?這個時候我們就看用他們經常會用到的工具和方法來驗證SM檢測的結果是否正確。

下面會從兩個維度去介紹影響流暢度的因素和相應的檢測工具。

從UI層優化入手

GPU 過度繪製+Trace for OpenGL

過度繪製:在屏幕一個像素上繪製多次,比如一個TextView後有背景,那麼顯示文本的像素至少繪製兩次,一次是背景,一次是文本。

小貼士

如何實現過度繪製:打開安卓手機,找到設置—》開發者選項—》調試GPU過度繪製打開。

古語有云:知己知彼,方能百戰百勝,我們想要比別人做的好,就要先了解一下自己和別人的差距,下面我們就比較一下淘寶、競品(更美,醫美分期的APP)還有么么錢包這三款APP 的過度繪製的情況。

淘寶 更美 么么錢包

從上面三個圖中可以看出界面上會出現各種顏色,顏色和過度繪製有什麼關聯呢? 可以看下下面的表格:

通過對比我們發現:

? 淘寶的首頁和顏色基本上藍綠色居多,過度繪製正常。

? 么么錢包的首頁基本上是綠色和淺紅色,過度繪製有待檢查。

? 更美的首頁顏色分佈大部分是偏向暗紅,過度繪製需檢查。

下面我們就以么么錢包【我的】頁面,來檢查下過度繪製:

我們看看是否可以優化,這些區域是怎麼形成的呢? 我們可以藉助於工具進行記錄和分析APP每一幀的繪製過程。

首先連接設備,然後打Android-sdk/tools/monitor.bat

1、點擊V字型的按鈕,會有個彈框:

2、填寫對應應用的信息

Device:連接的設備名稱

Application Package:應用對應的包名

Activity to launch:填寫應用對應的Main Activity

Destionation File:trace 保存的路徑

3、點擊【Trace】然後進入錄製頁面,此時打開APP到要檢查的頁面

點擊【Stop Tracing】

然後就可以通過trace文件進行分析:

通過演示我們發現:

? 列表部分【我的訂單】,兩次繪製之後沒有變化(按照正常情況,每繪製一次,都會有新增新繪製的UI)。

? 最後呈現的列表中的元素是在第一層刷完的上面進行疊加的。

對於上面發現的問題,給出初步的解決建議:

? 去掉多餘的繪製。

? 第一次繪製的時候,是否可以根據尺寸 提前設計好上半部分和小半部分背景顏色的設置(如:上面是黑灰色,下半部分是灰白色)

最後,把分析的結果提供給開發 優化的時候做下參考。

小貼士

並不是所有的有紅色部分就一定要修改的,這要根據UI情況而定,有些UI設計的比較複雜,紅色區域可能會多一點。

UI布局不合理+Hierarchy Viewer

UI的布局會影響到一個APP的視覺體驗,好的布局方式,往往能帶來舒服的視覺效果,更能得到用戶的接受與好評。

UI的布局可以通過Hierarchy Viewer這個工具來分析,主要分三種類型:

? 沒有用的父布局。是指沒有背景繪製或者沒有大小限制的父布局,這樣的父布局不會對UI效果產生任何影響,沒有用的父布局可以通過</merge>標籤合併來減少UI層次。

? 使用線性布局(LinearLayout)排版導致UI層次變深。如果遇到這種問題可以使用相對布局RelativeLayout代替LinearLayout,減少UI的層次。

? 不常用的UI被設置成了GONE,比如error頁面,請求網絡前不需要顯示的頁面。

下面來看看我們的么么錢包頁面的UI布局是怎樣的?

1. 首選 打開Android-sdk/tools/hierarchyviewer.bat

2. 選擇模擬器或者真機,找到對應的APP 的包名/MainActivity

3.點擊【Load View Hierarchy】

點擊後,UI布局如下圖:

根據上面介紹的三種類型,可以看到:

1、多處用到了線性布局,是否可以用RelativeLayout布局代替。

2、RelativeLayout從父布局到子布局沒有任何背景繪製,是否是沒有用的父布局。

把發現的問題可以反饋給開發,看看是否布局方式可以優化,圖中的標註已經和開發確認可優化。

從代碼層入手

Lint 掃描,發現代碼中的流暢度問題

Lint 掃描通過靜態掃描檢查代碼的方式,能夠發現在代碼中潛在的問題,並給出問題的原因和在代碼中的位置,並給出相應的優化建議。

如何進行Lint掃描呢?

首先 從GIT上下載APP的源碼,用AndroidStudio打開工程,選擇Analyze下的Inspect Code,會出現如下彈框:

根據檢查的範圍 自行選擇,然後點擊【OK】鍵,出現如下 等待檢測的進度框:

檢測完後就會展示檢測結果。

下面是抽取錢包部分代碼進行檢查,檢查結果如下:

我們從檢查結果可知,Lint掃描後會給出所有在這個項目中不規範的編碼、多餘的資源、可能的BUG、或者其它的一些問題,然後會給出相應的修改建議供我們參考,雖然有些問題並不會影響APP的正常運行,不過這對於項目的規範性和維護性來說是非常重要的。

Traceview,尋找卡主主線程的地方

我們在測試APP的時候,有時候會發現程序在運行一段時間後發現發燙、卡頓的現象,這時候我們可以藉助Traceview 工具進行分析。

Traceview 主要是找出主線程耗時較大的函數,減少調用。主要方式有以下兩種:

? 找出在主線程耗時較大的函數,看看能否通過優化邏輯去減少API的耗時。

? 分析滑動過程中CPU的工作,看看能否讓CPU優先執行主線程的工作,盡量不要被其他線程搶佔。

分析面板中各個指標的含義:

連接設備(模擬機或者真機),然後打開Android-sdk/tools/ddms.bat,選擇對應的應用

點擊上方的紅色帶點按鈕,紅色點會變成了灰色方塊,結束錄製後,再次點擊這個按鈕,就會彈出如下所示的分析數據圖:

由於本文討論的是和APP流暢度相關的,所以我們主要看兩個值 Cpu Time/Call和Call+Recur Calls/Total (單位是毫秒), 從Profile Pane 中可以看出 Cpu Time/Call和Call+Recur Calls/Total值都不大,在滑動過程中cpu佔用的時間分配比較合理,基本上都是主線程用。

那是不是這兩個值要是高就一定有問題呢?答案是不一定的,這要根據實際的業務場景來決定,從之前我的測試經驗看,分析這兩個值高大致的原因基本上就是:

1、業務邏輯複雜,主線程要處理的業務請求量多 CpuTime和Call+Recur Calls/Total佔用時間過長。

2、一個方法處理任務比較重,CpuTime和Call+Recur Calls/Total 佔用時間較長。

有時候我們測出來值偏高,但是不知道是不是代碼缺陷,這個時候我們測試可以提出一些疑問,把具體的父類調用的具體方法提供給開發,讓開發配合查下代碼,看看是不是可以優化。如果真的是代碼問題佔用時間過長,可以建議開發放到異步線程內處理。

總結

卡頓(ANR)問題的嚴重性,可能不像崩潰(Crash)來得那麼強烈,但對於用戶的流失影響是潛移默化,慢慢深入。我們在測試的時候,可以用上面講到的一些方法和工具處理並修復應用中的流暢度問題,確保我們提供的應用程序能夠給用戶提供優良的渲染性能,實現了平滑流暢的60FPS。

李敏

享米測試工程師