Instagram是如何提升TextView渲染性能的

ybny 9年前發布 | 28K 次閱讀 TextView Android開發 移動開發

來自:http://codethink.me/2015/04/23/improving-comment-rendering-on-android/
原文連接: Improving Comment Rendering on Android

上周,成千上萬來自全世界的IG用戶齊聚在社區組織的先下聚會 Worldwide InstaMeet11上。WWIM11 是歷史上最大,最具地域多樣性的Instagram聚會,從Muscat到Bushwick,成千上萬用戶分享了大約10萬張照片。

每月世界上有超過3億用戶每月使用IG,其中65%來自美國以外的國家,無論用戶在哪,我們一致致力于讓IG更快,更容易使用。自從去年夏天IG重新設計后,我們在繼續努力提升性能。

我們最近的一項改進是關于渲染龐大復雜的文本以及如何通過改進它優化IG的feed滾動。我們希望你可以從我們的經驗中找到提升自己app速度的方法。

產品需求和性能問題

在IG中,feed是由圖片,視頻和文字組成的。對于每個圖片和視頻,我們需要展示對應的圖片說明和5條最近的評論。由于用戶通常通過圖片說明來講書圖片背后的故事,這些圖片說明通常是大段復雜的文字,甚至可能包含鏈接和emoji表情。
Instagram是如何提升TextView渲染性能的
渲 染這種復雜文本的主要問題在于它滾動時對性能的影響。在Android中,文本的渲染是很慢的。即使在一個像Nexus 5這樣的新設備上,一段有十幾行復雜文本的圖片說明的初始繪制時間可能會達到50ms,而其文本的measure階段就需要30ms。這些都發生在UI線 程,在滾動時會導致app跳幀。

使用text.Layout,緩存text.Layout

Android有很多用于文字展示的控件,但實際上,他們都用text.Layout進行渲染。例如,TextView會將String轉化為一個text.Layout對象,并通過canvas API將它繪制到屏幕上。

由于text.Layout需要在構造函數中測量文本的高度,因此它的創建效率不高。緩存text.Layout和復用text.Layout實例 可以節省這部分時間。Android的TextView控件并沒有提供設置TextLayout的方法,但是添加一個這樣的方法并不困難:

Instagram是如何提升TextView渲染性能的

使用自定義的view來手動繪制text.Layout會提升其性能:TextView是一個包含大量特性的通用控件。如果我們只需要在屏幕上渲染靜態的,可點擊的文本,事情就簡單多了:

  • 我們可以不用從SpannableStringBuilder轉化到String。根據你的文本中是否包含鏈接,底層的TextView可能會復制一份你的字符串,這需要分配一些內存。

  • 我們可以一直使用StaticLayout,這比DynamicLayout要稍微快一些。

  • 我們可以避免使用TexView中其他的邏輯: 監聽文本修改的邏輯,展示嵌入drawable的邏輯,繪制編輯器的邏輯以及彈出下拉列表的邏輯。

通過使用TextLayoutView,我們可以緩存和復用text.Layout,從而避免了每次調用TextView的setText(CharSequence c)方法時都要花費20ms來創建它。

下載feed后準備好Layout緩存

由于我們確定會在下載評論后展示他們,一個簡單的改進是在下載它們后就準備好text.Layout的緩存。
Instagram是如何提升TextView渲染性能的

停止滾動后準備好TextLayoutCache

在可以設置text.Layout緩存后,我們的到來常數級的測量(measure)和綁定(binding)時間。但是初次繪制的時間仍然很長。50ms的繪制時間可能會導致明顯的卡頓。

這50ms中的大部分被用于測量文本高度以及產生文字符號。這些都是CPU操作。為了提升文本渲染速度,Android在ICS中引入了 TextLayoutCache用于緩存這些中間結果。TextLayoutCache是一個LRU緩存,緩存的key是文本。如果查詢緩存時命中,文本 的繪制速度會有很大提升。

在我們的測試中,這種緩存可以將繪制時間從30ms-50ms減少到2ms-6ms。
Instagram是如何提升TextView渲染性能的
為了更好的提升繪制性能,我們可以在繪制文本到屏幕前準備好這個緩存。我們的思路是在一塊屏幕外的canvas上虛擬的繪制這些文本。這樣在我們繪制文本到屏幕前,TextLayoutCache就已經在一個背景線程中被準備好了。
Instagram是如何提升TextView渲染性能的
默認情況下,TextLayoutCache的大小為0.5M,這足以緩存十幾張圖片的評論。我們決定在用戶停止滑動時準備緩存,我們向用戶滑動的方向提前緩存5個圖片的評論。在任何時候,我們都至少在任何一個方向上緩存了5個圖片的評論。
Instagram是如何提升TextView渲染性能的

在應用了所有的這些優化后,掉幀情況減少了60%,而卡頓的情況減少了50%。我們希望這些能幫助你提升你app的速度和性能。告訴我們你的想法吧,我們期待聽到你的經驗。

 本文由用戶 ybny 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!