雖然如今RecycleView大行其道伦腐,但作為老牌控件listview仍應(yīng)用廣泛灾搏,但真正使用時(shí)泄伪,由于業(yè)務(wù)上的需求以及開發(fā)人員的理解不深入殴蓬,使得listview性能并不十分高,造成卡頓
那么先從以下幾點(diǎn)進(jìn)行測(cè)試
- 父布局類型(相對(duì),線性)
- 布局嵌套深度
XML布局代碼
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="添加數(shù)據(jù)"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onToggle"
android:text="顯示/隱藏"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"/>
<com.hhwant.speed.app.TestListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="200dp"
>
</com.hhwant.speed.app.TestListView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
根布局LinearLayout染厅,再嵌套3層LinearLayout痘绎,內(nèi)置一個(gè)自定義Listview,自定義Listview的代碼很簡(jiǎn)單肖粮,只是單純?cè)趏nMeasure打印一段話
public class TestListView extends ListView {
private static final String TAG = "TestListView";
public TestListView(Context context) {
super(context);
}
public TestListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TestListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d(TAG, "onMeasure");
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
先看LinearLayout多層嵌套下的效果
- 可以見到的是在LinearLayout嵌套了3層的情況下,進(jìn)入界面初始化調(diào)用了2次onMeasure()
- 讓與listview同層級(jí)的imageview消失(GONE)后孤页,不會(huì)間接觸發(fā)listview調(diào)用onMeasure
- 讓listview里的item圖片visible或者gone,會(huì)同樣的讓listview調(diào)用一個(gè)onMeasure
那么給ListView設(shè)置權(quán)重以后再看效果
- 和前者的不同之處在于設(shè)置了權(quán)重以后涩馆,listview同級(jí)的imageview設(shè)置visible和gone后行施,會(huì)間接讓listview重新調(diào)用onMeasure來(lái)重新計(jì)算listview的高度
再來(lái)看看RelativeLayout多層嵌套下的效果
- 可以見到的是在RelativeLayout嵌套了3層的情況下,進(jìn)入界面初始化調(diào)用了16次onMeasure() ,即2^4
- 讓與listview同層級(jí)的imageview消失(GONE)后,會(huì)間接觸發(fā)listview調(diào)用8次onMeasure,即2^3
- 讓listview里的item圖片visible或者gone魂那,會(huì)同樣的讓listview調(diào)用8次onMeasure,即2^3
因RelativeLayout的特殊性蛾号,功能的豐富性同時(shí)導(dǎo)致了其性能的低下,在界面初始化時(shí)需調(diào)用兩次onMeasure()涯雅,而RelativeLayout內(nèi)部的onMeasure方法更是需要遍歷子view鲜结,分別橫向和縱向測(cè)量子view
那么我們可以得出一個(gè)結(jié)論,在能實(shí)現(xiàn)需求和功能的前提下斩芭,基礎(chǔ)布局盡量不選擇RelativeLayout轻腺,特別是ListView在RelativeLayout的嵌套下,多次調(diào)用onMeasure(),而ListView又在onMeasure調(diào)用了getView划乖,大部分的邏輯在getView中贬养,指數(shù)次調(diào)用必然導(dǎo)致性能的大幅下降
參考資料
Android應(yīng)用性能優(yōu)化系列視圖篇——三大基礎(chǔ)布局性能比較
Android應(yīng)用性能優(yōu)化系列視圖篇——ListView自適應(yīng)導(dǎo)致的嚴(yán)重性能問(wèn)題
Android源碼(這個(gè)就自己進(jìn)布局源碼看吧)