佈局性能優化:安卓開發者不可錯過的性能優化技巧

語言: CN / TW / HK

theme: fancy

今天總結一下佈局的性能優化,這是一個系列,上一篇是# 內存泄漏大集結:安卓開發者不可錯過的性能優化技巧 也可以看性能優化專欄裏的記錄,都是非常好的開發經驗。

當我們開發Android應用時,佈局性能優化是一個必不可少的過程。一個高效的佈局能夠提高用户體驗,使應用更加流暢、響應更加迅速,而低效的佈局則會導致應用的運行變得緩慢,甚至出現卡頓、崩潰等問題,影響用户體驗。在開發中,佈局優化不僅需要考慮到UI設計的美觀性和易用性,還需要關注佈局的性能,避免出現因視圖過多、嵌套過深、圖片過大等問題導致的性能瓶頸。通過對佈局進行優化,可以顯著提高應用的性能和用户體驗,減少應用的CPU和內存佔用,加快應用的啟動和響應速度,降低應用的耗電量,從而提高應用的穩定性和可靠性。

佈局性能優化對於提高Android應用的質量和競爭力是至關重要的。在實際開發中,我們需要根據具體的業務場景和設計要求,結合佈局優化的最佳實踐,逐步提升應用的佈局性能,為用户帶來更好的體驗。

佈局為什麼會有性能問題呢

那需要了解一下Android View的渲染機制,Android渲染機制是指Android系統中用於顯示界面的工作流程。它包括視圖樹的構建、測量、佈局和繪製四個過程。

他們的大致流程是 mermaid graph TD 構建視圖樹 --> 測量 --> 佈局 --> 繪製

  1. 構建視圖樹(View Hierarchy):在應用啟動時,Android系統會根據佈局文件中定義的View、ViewGroup和其他組件創建一個視圖樹。視圖樹是根據xml進行解析的。
  2. 測量(Measure):在測量過程中,系統會遍歷視圖樹,並計算每個視圖的大小和位置
  3. 佈局(Layout):在佈局過程中,系統會根據視圖樹中每個視圖的測量結果,確定每個視圖的大小和位置,並將其放置在正確的位置上
  4. 繪製(Draw):在繪製過程中,系統會遍歷視圖樹,並將每個視圖繪製到屏幕上

在這幾個過程中,佈局過程是比較耗費時間的,並且耗時與視圖樹的複雜程度成正比。

複雜的佈局指的是樹關係的複雜,而不是元素的複雜。

不一樣的角度

從系統角度分析,Android系統的UI界面是基於視圖層次結構(View Hierarchy)構建的,每個UI元素都是View或ViewGroup對象的實例,這些對象按照它們在界面中出現的順序排列,構成了一個視圖層次結構。在這個結構中,每個UI元素都有自己的父元素和子元素,因此構成了一個樹形結構。這個樹形結構的根節點是一個ViewGroup對象,它是整個視圖層次結構的根。

當用户進行交互操作時,Android系統需要對視圖層次結構進行更新,例如重新佈局、重繪等操作,這些操作會消耗大量的CPU和內存資源。因此,視圖層次結構的構建對應用程序的性能和響應速度至關重要。

常見佈局解析,用對了,你的性能問題會減少很多

我們從開始學習Android就知道五大布局是Android的佈局基礎,大家還記得他們的優缺點嗎?之所以有五大布局,就是因為他們使用場景各不相同,然而有時候寫法就是上來就相對,別的不考慮,這正確嗎?

這是一個對比表格,加顏色的,年齡小的程序員可能都不知道。

image.png

通過這個對比,你會發現,每一個佈局都有它的用途,要是用對了,在性能方面都有提升。也不是説用約束佈局一擼到底,在有些專場的場景中,對應的佈局更加優於約束佈局。

回顧完之後,我們看看開發中還有哪些影響性能的寫法。

常見的開發中有損佈局性能的操作方式

嵌套層數過多

當一個佈局容器包含多個子佈局容器時,會導致視圖層次結構的深度增加,從而增加了CPU和內存資源的消耗 ``` <LinearLayout

<RelativeLayout
</RelativeLayout>
<LinearLayout
    >

</LinearLayout>

```

內存使用過高

當一個佈局容器包含大量的子視圖時,會導致內存佔用過高,從而影響應用程序的性能

```

```

不合適的佈局容器

在佈局中選擇合適的佈局容器可以避免不必要的佈局操作和內存消耗(當需要顯示大量的數據列表時,使用ListView或RecyclerView等容器可以避免不必要的視圖更新和內存消耗)

過多的重繪操作

當一個佈局容器中包含多個視圖時,每次修改其中一個視圖的屬性,都會導致整個佈局容器的重繪操作

可以使用ViewStub元素來延遲加載複雜的視圖。

不合理的佈局屬性

在佈局中選擇合適的佈局屬性可以避免不必要的視圖更新和內存消耗

在使用RelativeLayout佈局容器時,它的測量和佈局都需要參考父、兄等原則,所以需要考慮到視圖的相對位置和大小,以避免不必要的佈局操作和內存消耗。

使用無效的佈局容器

在佈局中使用無效的佈局容器會增加不必要的佈局操作和內存消耗,影響應用程序的性能和響應速度

```

```

這種操作在開發中還是比較常見的,有時候為了給Text View或者ImageView 添加點擊區域,外邊搞一個FragmeLayout。這種操作會導致內存消耗過高的。

常見的檢測佈局性能工具

  1. Hierarchy Viewer工具:Hierarchy Viewer工具可以幫助開發者分析應用程序的視圖層次結構,找出可能存在的性能問題。在Hierarchy Viewer中,可以查看應用程序的視圖層次結構,以及每個視圖的繪製時間、測量時間和佈局時間等性能指標。
  2. TraceView工具:TraceView工具可以幫助開發者分析應用程序的性能問題,包括佈局性能問題。在TraceView中,可以查看應用程序的方法調用鏈和執行時間等信息,以及每個方法的CPU使用率、內存消耗等性能指標。
  3. UI性能分析器:Android Studio中內置了UI性能分析器,可以幫助開發者分析應用程序的UI性能問題,包括佈局性能問題。在UI性能分析器中,可以查看應用程序的渲染時間、FPS、佈局時間等性能指標,並根據性能指標分析應用程序的性能問題。
  4. Monkey測試工具:Monkey測試工具可以幫助開發者測試應用程序的穩定性和性能問題,包括佈局性能問題。在Monkey測試中,可以模擬用户隨機點擊和滑動操作,以測試應用程序的穩定性和響應速度,同時可以通過TraceView等工具分析應用程序的性能問題。(提前做好監測的買點,trace收集,然後用monkey測試,最後分析trace)

總結

1.減少佈局層次

佈局層次越深,繪製所需的時間就越長,因此應該儘可能減少佈局層次。可以通過使用 ConstraintLayout 或者自定義 View 來減少佈局層次。

2.使用合適的佈局容器

應該選擇最適合當前佈局需求的佈局容器,避免使用過於複雜的佈局容器,比如 LinearLayout 嵌套多層、RelativeLayout 的多重嵌套等。

3.使用 ViewStub 來延遲加載視圖

如果佈局中包含複雜的視圖,可以考慮使用 ViewStub 來延遲加載這些視圖,以減少佈局的加載時間。

4.避免使用過多的嵌套佈局

嵌套佈局會增加布局的複雜度,導致渲染時間變長。因此應該儘量避免過多的嵌套佈局。

5.使用合適的佈局屬性

合理使用佈局屬性可以讓佈局更加簡潔、高效,比如使用 match_parent 和 wrap_content 來替代具體的像素值。

6.避免在佈局文件中使用過多的 include 標籤

include 標籤可以重複使用佈局,但是過多的使用會增加布局層次和渲染時間,因此應該儘量避免在佈局文件中使用過多的 include 標籤

主要是要弄明白布局的使用場景,從這幾個坑出發,寫代碼的時候上點心。

另外學習約束佈局有一個很好的博客推薦大家# 萬字長文 - 史上最全ConstraintLayout(約束佈局)使用詳解