? ? ? ?我們向全球最流行的一些 App 的開發團隊(包括微信,雅虎新聞摘要)取經了開發流暢 App 的最佳實踐經驗。通過我們自己的經驗以及與這些頂尖開發者的交流,我們發現開發優秀 App 最重要的實踐經驗是建立一個性能優化的流程:如何讓你的App更流暢優化過程? ? ? ?當你的 App 性能不佳時,持續測量 App 的性能表現就變得尤為重要。一旦檢測出性能問題,你應專注于對問題尋根溯源。診斷可能還會用到更多的測量和詳細的性能數據,使你一段時間內陷入我們稱之為“測量-分析循環”的怪圈。即使在找到問題的根本原因后,光修復爛代碼還不夠。你還得重新驗證各項指標來確定修復是有效的。這就意味著更多的測量。測量? ? ? ?有兩個最為影響用戶體驗 (UX) 的性能指標。第一,我們要注意的是響應時間:你的 App 要花多久時間來響應用戶的操作 (比如啟動 App, 瀏覽新文章, 加載聯系人名單, 或者打開 Facebook 頁面)。假如你的 App 在所有上述情景中都能迅速響應,這將幫助你建立一個更好更完美的用戶體驗。? ? ? ?一個關鍵(而獨特)的響應時間的例子是啟動時間。App 的啟動是裝了這個 App 的用戶的第一次用戶體驗, 而第一印象又是最重要的。事實是,有關于軟件的研究發現79%的用戶在裝了有啟動問題的 App 后只重試了一兩次就卸載了。以下是 我們給出的一些建議,我們在軟件性能及優化領域有著多年經驗。? ? ? ?我們建議不要讓你的 App 花在啟動上的時間超過兩秒,因為這是用戶期待中 App 啟動的平均時間。熟悉網頁性能的都知道,47%的用戶希望頁面能在兩秒以內加載完畢,而用戶們在外趕時間時花在移動端 App 上的耐心就更少了。建議一:兩秒內使 App 啟動? ? ? ?第二個重要指標是流暢度。即使一個 App 總體上來看響應時間很短,響應本身必須也要流暢,使“卡頓”盡可能少。用戶對時間上的卡頓非常敏感,意味著即使是小小的頓挫也會影響用戶體驗。平均來說,人眼能分辨小到 22 毫秒的卡頓,而四分之一的人群能察覺 2 毫秒到 16 毫秒的卡頓 – 60幀每秒 (FPS) 的刷新率就是根據這個原理。? ? ? ?你可以從你的 App 的 FPS 和幀時間數據得出 App 的流暢度。然而請注意這數據不會告訴你你的 App 的性能問題根源所在,這就意味著它沒法幫你找到 App 卡頓的 method。? ? ? ?在安卓系統中,用戶界面 (UI) 線程 (你的 App 執行的主線程) 是唯一能對用戶界面進行更新的線程。要保持一個 60 FPS 的刷新率,UI線程必須在每 16 毫秒內完成一幀的繪制。如果在 UI 線程上的任何 method 的調用時間超出了這一時間, 你的 App 就會掉幀, 產生時間上的卡頓。更糟的是此時你的 App 對任何的用戶操作都無響應,因為 UI 線程還在被這個 method 調用所占據。? ? ? ?實際上,要確保 UI 線程的每一個 method 的調用時間都少于16毫秒是幾乎不可能的。32 毫秒的門檻值,相當于兩個幀的長度,才更合理。我們把超出這個門檻值 (執行時間超出32毫秒) 的 methods 叫做掛起 methods,因為它們使得 App 看上去“掛起”了。為了使你的 App 絲般順滑,收獲更佳的用戶體驗, 消除所有的掛起 methods 將大有裨益。建議二:消除掛起 methods? ? ? ?好 吧。既然測量同用戶體驗相關的指標是如此重要,那么我們該多久測量一次指標呢?每個版本?每個日版本?在每次發布之前?在生產中?!你應當一有機會就進行測量 —— 測量的頻率越高,你就能越早發現和補救性能問題。同我們交流的 Yahoo 團隊在每次發布前對 App 的性能進行采樣,而微信團隊對每個日版本進行性能采樣。建議三:盡可能多測量分析? ? ? ?優化你的軟件的關鍵是找到常規的性能問題并系統地從你的代碼中剔除。在對有著超過五百萬次下載記錄的 App 的性能問題分析中,我們觀察到開發者經常使用在桌面端高效卻在移動端低效的代碼結構。舉個例子,在一臺 MacBook Air 上一個 JAR 文件調用methodClassLoader.getResourceAsStream 處理3K 資源的花銷約為 7 毫秒, 而在一臺 2013 年的 Nexus 7 上一個 APK 文件調用這個 method 同樣處理3K 資源的花銷約為 1700 毫秒。后來發現,安卓對于getResourceAsStream 的執行是在第一次調用時做了大量的額外工作,如為 APK 文件里的所有資源編排索引,驗證 APK 文件的證書, 并解析其 manifest。這種操作是相當耗費 CPU 資源的,從而導致 App 的嚴重時滯 ——getResourceAsStream 給 Walgreens App 造成了 1.7 秒的時滯。建議四:了解一些通病? ? ? ?有時性能問題是由你使用的第三方 SDKs 引起的,而并非你的代碼。這些問題就很難被發現。譬如說org.joda.time ,Java中一個流行的時間庫。你可能在以往的Java項目上使用過它。結果僅僅是創建一個 org.joda.time.DateTime 對象就造成了巨大的時滯 —— Yahoo Fantasy Sports App 性能被它拖慢了兩秒之多。這是因為org.joda.time.DateTime 使用getResourceAsStream 來從 APK 文件加載時區數據。建議五:避免第三方 SDKs 帶來的麻煩優化? ? ? ?修復爛代碼可能成為噩夢般的過程。要從上百個進程中找出拖慢 App 的進程,這種尋根溯源的任務可能會占據數周的開發周期。盡管如此,還是有一些通用的指導方針的。使用更有效的數據表現方式,算法,和執行方式或(萬一你使用的是SDK從而無法直接修復代碼的話)在后臺線程調用代碼而避免掛起在 UI 線程發生,這里面任意一種方式,都能使你的代碼運行得更快。遵循這些指導方針使 App 更有效率,大大有益于創造出人見人愛的產品。去哪尋求幫助? ? ? ?盡管性能優化過程幫助你的 App 運行順暢,它也需要花費時間和一點點魔力來實施。這正是為什么我們要開發安卓快速開發,強力優化以及性能采樣工具的原因,這樣你們就能不分心地專注于你們的強項:為用戶帶來了不起的產品。