性能探究之onMeasure

来源:互联网 发布:linux删除samba用户 编辑:程序博客网 时间:2024/05/20 20:39

虽然如今RecycleView大行其道,但作为老牌控件listview仍应用广泛,但真正使用时,由于业务上的需求以及开发人员的理解不深入,使得listview性能并不十分高,造成卡顿

那么先从以下几点进行测试

  • 父布局类型(相对,线性)
  • 布局嵌套深度

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="添加数据"/>    <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,内置一个自定义Listview,自定义Listview的代码很简单,只是单纯在onMeasure打印一段话

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_listview

  • 可以见到的是在LinearLayout嵌套了3层的情况下,进入界面初始化调用了2次onMeasure()
  • 让与listview同层级的imageview消失(GONE)后,不会间接触发listview调用onMeasure
  • 让listview里的item图片visible或者gone,会同样的让listview调用一个onMeasure

那么给ListView设置权重以后再看效果

  • 和前者的不同之处在于设置了权重以后,listview同级的imageview设置visible和gone后,会间接让listview重新调用onMeasure来重新计算listview的高度

再来看看RelativeLayout多层嵌套下的效果

  • 可以见到的是在RelativeLayout嵌套了3层的情况下,进入界面初始化调用了16次onMeasure() ,即24
  • 让与listview同层级的imageview消失(GONE)后,会间接触发listview调用8次onMeasure,即23
  • 让listview里的item图片visible或者gone,会同样的让listview调用8次onMeasure,即23

因RelativeLayout的特殊性,功能的丰富性同时导致了其性能的低下,在界面初始化时需调用两次onMeasure(),而RelativeLayout内部的onMeasure方法更是需要遍历子view,分别横向和纵向测量子view

那么我们可以得出一个结论,在能实现需求和功能的前提下,基础布局尽量不选择RelativeLayout,特别是ListView在RelativeLayout的嵌套下,多次调用onMeasure(),而ListView又在onMeasure调用了getView,大部分的逻辑在getView中,指数次调用必然导致性能的大幅下降

参考资料

Android应用性能优化系列视图篇——三大基础布局性能比较
Android应用性能优化系列视图篇——ListView自适应导致的严重性能问题
Android源码(这个就自己进布局源码看吧)

0 0
原创粉丝点击