Android中佈局的優化

個人掘金地址android

#本文涉及到的知識點bash

  • 簡單的說明如下佈局優化的重要性
  • 一些佈局使用的注意事項
  • include、merge與ViewStub的使用
  • ConstraintLayout的使用

##1.佈局優化的重要性工具

在平常開發中對於佈局咱們不多注重性能,主要注重的就是相應的展現問題。可能因爲界面的複雜程度,使得界面嵌套的層級過多,這樣也就致使了繪製頁面的卡頓現象。增長了GPU渲染的複雜程度。這裏引用一張圖片來講明相應的問題。佈局

GPU過分繪製參考圖

怎麼查看呢?手機設置->開發者選項->調試GPU過分渲染 打開以後你就能看到你的APP到底有沒有過分繪製了。若是你看見的是一片紅,那麼恭喜你...你必須考慮相應的優化了!說了這麼多,其實最重要的就是減小層級、減小相應的過分繪製,就能有效的對佈局進行相應的優化。因此在Android作一些簡單的佈局優化仍是有必要的。。。性能

##2.一些佈局使用的注意事項flex

這裏先提出個問題,你們想一下?若是項目中有這樣一個需求,豎直排列兩行每行兩個元素,你們怎麼去實現呢?相信有的人會使用相對佈局,有的人會使用線性佈局,那麼問題就來了,若是你使用線性佈局的話,就會存在佈局嵌套的問題,就平白的多了一層佈局嵌套,平時開發的時候這樣的問題不少,若是你多加註意的話,你會發現不少這樣的問題。優化

這裏我主要想說的是,若是在平時開發佈局的時候,若是在佈局不是很複雜的狀況下儘可能使用相對佈局,少用線性佈局。可是你們要注意一點,若是佈局複雜的話,或者層級較深的狀況下,最好仍是使用線性佈局。這裏不知道你們注意沒有,在Android Studio2.+版本的時候,全部默認的佈局都是線性佈局,爲何呢?我就不在繼續深刻講解了,感興趣的同窗能夠看看尹star 的->Android中RelativeLayout和LinearLayout性能分析主要是Measure在測量的時候產生的性能消耗!因此這個問題主要看你佈局是否比較複雜。。。其實在如今的版本中,google推薦咱們使用的是ConstraintLayout(這個我會在後面詳細的講解)google

##3.include、merge與ViewStub的使用spa

說到佈局優化問題,很難不說起include、merge與ViewStub的使用,可是這些都有相對的侷限性的,下面咱們就來一一講解:調試

###3.1 include的使用和注意事項

這個東西相信你們都不陌生,它能幫咱們解決佈局複用的問題,只要include導入一個佈局就能夠了。像這樣:

<include layout="@layout/XXX"/>
複製代碼

XXX表明引入的佈局。是否是很簡單,那麼我問你們幾個問題?

  • 若是在include標籤中我設置相應的layoutxxx的屬性,會對原來的佈局有什麼影響?
  • 若是在include標籤中我設置了id,會對原來的佈局有什麼影響?

這些問題,相信細心的人應該會有體會的,可是對於有些人來講,或許很陌生。因此這裏有必要說明一下:

  • 當你在include中設置layoutxxx屬性的時候,會覆蓋相應導入根佈局的layoutxxx屬性,怎麼理解呢?也就是說若是你導入的佈局是這樣的
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#223344"
        android:gravity="center"
        android:text="導入的佈局"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

</LinearLayout>
複製代碼

這裏看好,LinearLayout的寬和高是佔用父窗體。若是你要是這麼寫

<include layout="@layout/test_view" />
複製代碼

的話,會顯示全屏的,就像這個樣子

沒有設置layoutxxx的屬性

可是若是你要是寫成這個樣子就不同了

<include
        layout="@layout/test_view"
        android:layout_width="200dp"
        android:layout_height="200dp" />
複製代碼

會變成這個樣子

設置了layoutxxx的屬性

這裏要特別注意一下。。。

  • 當你在include中設置id的時候,會覆蓋相應導入根佈局的id屬性,也就是說你只能使用include中的id屬性獲取根view了!

###3.2 merge的使用和注意事項

對於新手來講,這個標籤應該不多使用,至少我是這樣的,其實我呆了這麼多公司,也不多有人去用這個,可能我呆的都是小公司吧!哈哈。。。不閒扯了,其實這個標籤主要是針對include導入的標籤的根佈局來講的,能夠減小一個層級的嵌套!

先來講一下這個怎麼看啊!!!不說這個的都是扯淡。。。在Android Studio3.+版本上按照下圖獲取!

查看視圖樹的工具

中間會彈出一個對話框,而後你就點肯定,就能查看相應的視圖樹了。。。

  • 當你沒有使用merge標籤的時候,佈局是這個樣子的!
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#223344"
        android:gravity="center"
        android:text="導入的佈局"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

</LinearLayout>
複製代碼

這個時候你查看一下視圖樹你會發現會出現下面這個樣子。

未使用merge標籤的視圖層級

我已經用紅框畫出來了,中間有一層LinearLayout做爲根佈局,可是若是你把上面的LinearLayout換成merge標籤就不會有中間這層LinearLayout了。這個就不貼圖了,不信的你能夠試試。。。

還有一個問題須要注意: 這裏有必要說明一下,若是你要給merge標籤設置一些屬性怎麼辦?實際上是這樣的,你能夠根據include的父控件進行屬性的設置,若是父控件是LinearLayout你就能夠設置weidge或者相應LinearLayout的特有屬性...這也充分說明了爲何include可使用layoutxxx屬性覆蓋根佈局的layoutxxx屬性。

###3.3 ViewStub的使用和注意事項

其實關於這個ViewStub這個標籤,就至關於延時加載,可是有不少侷限性,打個比方說吧!相應在平時開發的時候,都會根據狀態進行一些控件的顯示和隱藏吧,通常的處理都是View的setVisibility();可是這裏若是你改變一次以後還能進行改變的話,那麼就不能使用ViewStub這個標籤。由於ViewStub對控件只有一次的改變,其實ViewStub在佈局加載的時候已經加載出來了,只是寬和高都是0罷了,當你inflate()的時候,再去加載這個總體的View,達到了延遲加載的目的!

基本的寫法就是這樣,也是導入一個layout

<ViewStub
        android:id="@+id/vs_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout="@layout/test_view" />
複製代碼

何時你想加載了,就調用View inflate = mVs.inflate();方法就能讓這個View顯示出來,可是必定要注意,這個方法只能使用一次,切記!切記!切記!重要的事情說三遍,當這個View加載出來的時候,你就能夠像對待其餘View對待它了,若是你要對這個View作一些特有控件的操做,最好強轉一下。。。

基本上上面這三個View優化的標籤我總結的就這麼多,有什麼不對的還請指出,我會當即改正的!!!

##4. ConstraintLayout的使用

關於這個控件,其實google早在很早的時候就讓咱們去嘗試着使用了,可是在1.0.2那個版本的時候(記不太清楚了)才做爲根佈局使用的。

A ConstraintLayout is a ViewGroup which allows you to position and size widgets in a flexible way. Note: ConstraintLayout is available as a support library that you can use on Android systems starting with API level 9 (Gingerbread). As such, we are planning on enriching its API and capabilities over time. This documentation will reflect those changes.

這裏面引用了google的解釋,大概的意思是

ConstraintLayout繼承ViewGroup容許您以靈活的方式定位和調整小部件的大小。 ConstraintLayout可用做支持庫,您能夠從API級別9(薑餅)開始在Android系統上使用該支持庫。所以,咱們計劃在一段時間內豐富其API和功能。本文檔將反映這些更改。

主要是約束內部控件位置的佈局,裏面包含關於相對位置的屬性:

  • layout_constraintLeft_toLeftOf 當前控件的左側和目標控件的左側對齊
  • layout_constraintLeft_toRightOf 當前控件的左側和目標控件的右側對齊
  • layout_constraintRight_toLeftOf
  • layout_constraintRight_toRightOf
  • layout_constraintTop_toTopOf
  • layout_constraintTop_toBottomOf
  • layout_constraintBottom_toTopOf
  • layout_constraintBottom_toBottomOf
  • layout_constraintStart_toEndOf
  • layout_constraintStart_toStartOf
  • layout_constraintEnd_toStartOf
  • layout_constraintEnd_toEndOf

其實屬性不少,估計讓你記你也記不住,因此總結一下:

這裏全部的均可以這麼去理解,layout_xxxA_toxxxB 理解爲,當前控件的A側和目標控件的B側對齊,你可能仍是不理解,拿第一個舉例說明下,就是當前控件的左側和目標控件的左側對齊,標記了兩個,其餘的以此類推。這裏注意裏面設置的參數是目標控件的id/父容器只有這兩種可能! 若是你有兩個控件,左側的以父控件對齊,另外一個控件以左側的控件對齊,這時候若是右側以父控件對齊的話,這個控件會在右側剩下的空間居中(像下面這樣),可是若是你要是不設置右側的屬性的話,那麼兩個會挨着!(是那個屬性拆散了它們!哈哈)

  • layout_constraintHorizontal_bias 水平誤差百分比
  • layout_constraintVertical_bias 豎直誤差的百分比

這兩個屬性是針對於上面這個產生誤差的(只能設置覺得小數,最大是1),其實我試過,只要你左右或者上下都有約束的時候,這個相應的屬性才生效,不然是無效的(如:一個控件左右都有約束,那麼設置layout_constraintHorizontal_bias纔會生效,不然是不會生效的,豎直方向的同理)

  • android:layout_marginStart
  • android:layout_marginEnd
  • android:layout_marginLeft
  • android:layout_marginTop
  • android:layout_marginRight
  • android:layout_marginBottom

若是你設置了相應的margin_xxx屬性,那麼主要是產生了相應的邊距,和其餘的控件都同樣,這裏就再也不多作解釋了.

  • layout_goneMarginStart
  • layout_goneMarginEnd
  • layout_goneMarginLeft
  • layout_goneMarginTop
  • layout_goneMarginRight
  • layout_goneMarginBottom

這裏說明一個問題,當你有一個View處於GONE的狀況,其餘View還以來這個View來進行佈局,那麼就須要設置上面的goneMarginXXX來設置相應的Margin**(PS:這個只有在你依賴的那個約束爲GONE的時候纔會生效的屬性)**

  • android:minWidth 設置佈局的最小寬度
  • android:minHeight 設置佈局的最小高度
  • android:maxWidth 設置佈局的最大寬度
  • android:maxHeight 設置佈局的最大高度

這幾個屬性沒有什麼好說的了!

  • layout_constraintDimensionRatio 設置寬高比

這個屬性頗有意思:設置相應的寬高比,可是我試了,至少要有三面有約束,不然不起做用,而且寬度和高度都應該設置成"0",參數值能夠是"1:1"或者"h,1:1"也能夠是"w,1:1"其中h表明限制高度,w表明限制寬度.這裏的比例無論你前面是什麼,後面的比值都是"寬度:高度"

  • layout_constraintHorizontal_weight
  • layout_constraintVertical_weight

這兩個屬性至關於LinearLayout的weight屬性和LinearLayout的屬性設置是同樣的

  • layout_constraintHorizontal_chainStyle
  • layout_constraintVertical_chainStyle
    • CHAIN_SPREAD 默認樣式(若是某些小部件設置爲MATCH_CONSTRAINT,則它們將拆分可用空間)
    • CHAIN_SPREAD_INSIDE 但鏈條的終點不會被分散
    • CHAIN_PACKED 鏈條的元素將被打包在一塊兒。

樣式說明

這裏我用的時候踩了一個大坑,這裏所謂的鏈式,你必須確保從左至右或者從上至下多有的約束都連着,這裏的連着是都有相應的約束: 如view a 和view b在豎直方向上造成鎖鏈:a的屬性設置爲 top_toTopOf = 「parent」 bottom_toTopOf = 「b」 b的屬性設置爲top_toBottomOf=「a」 bottom_toBottom = 「parent"切記!切記!切記!都要連上....重要的事情說三遍,不然你是看不見效果的.效果就是上面這張圖的效果!

這裏使用了這個佈局,就能減小布局的嵌套,也使得繪製的時候能減小GPU的負擔,這樣就能達到佈局優化的目的了!!!

上面這些......基本上就是我在項目中優化佈局時候所作的一些優化,有什麼不妥的地方還請指正!


歡迎關注個人公衆號
相關文章
相關標籤/搜索