• Relativelayout和LinearLayout对比分析


    分析之前先了解下View的绘制流程

         首先view在windows中的布局样式如下图:

    view绘制在windows,windows与DecoverView的交互在VIewRoot中进行。

    view绘制的入口函数是ViewRootImpl中的performTraversals, performTraversals钟会一次调用performMeasure、performLayout、performDraw,三个函数中会分别调用view.Measure、view.Layout、view.Draw,然后分别调用需要子类实现的onMeasure、onLayout、onDraw函数。

    而继承自view的自定义view或者系统写好的textview或者LinearLayout等实例化的onMeasure、onLayout、onDraw函数分别用于测量view大小,摆放view、以及将view画出来。

    LinearLayout继承自viewGroup,在onMeasure中,会分别调用子控件的view.Measure, 进而在子控件的onMeasur中完成测量,如果子控件仍然是一个viewGroup则依次下去。

    view绘制各重载函数的执行流程:

          1、android:visibility=visible
    创建
    I/TestView: TestView(Context context, AttributeSet attrs) I/TestView: onFinishInflate() I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{2192bad9 I.E..... R.....ID 0,0-0,0} visibility = 4 I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{2192bad9 V.E..... R.....ID 0,0-0,0} visibility = 0 I/TestView: onAttachedToWindow() I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016 I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 2192 oldw = 0 oldh0 I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2248 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820 I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 1996 oldw = 1328 oldh2192 I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2052 I/TestView: onDraw(Canvas canvas) I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820 I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = false left = 56 top = 56 right = 1384 bottom = 2052 I/TestView: onDraw(Canvas canvas)
    销毁
    I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8 I/TestView: onDetachedFromWindow()

    2、android:visibility=invisible

    创建
    I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.example.junyizhou.rxjavademo.TestView{3ead3d52 I.ED.... ........ 0,0-0,0} visibility = 4 I/TestView: TestView(Context context, AttributeSet attrs) I/TestView: onFinishInflate() I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 I.E..... R.....ID 0,0-0,0} visibility = 4 I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 V.E..... R.....ID 0,0-0,0} visibility = 0 I/TestView: onAttachedToWindow() I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743848 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073744016 I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 2192 oldw = 0 oldh0 I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2248 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820 I/TestView: onSizeChanged(int w, int h, int oldw, int oldh) w = 1328 h = 1996 oldw = 1328 oldh2192 I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = true left = 56 top = 56 right = 1384 bottom = 2052 I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820 I/TestView: onMeasure(int widthMeasureSpec, int heightMeasureSpec) widthMeasureSpec = 1073743152 heightMeasureSpec = 1073743820 I/TestView: onLayout(boolean changed, int left, int top, int right, int bottom) changed = false left = 56 top = 56 right = 1384 bottom = 2052
    销毁
    I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8 I/TestView: onDetachedFromWindow()

    3、android:visibility=gone

    创建

    I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.example.junyizhou.rxjavademo.TestView{3ead3d52 G.ED.... ......I. 0,0-0,0} visibility = 8
    I/TestView: TestView(Context context, AttributeSet attrs)
    I/TestView: onFinishInflate()
    I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 I.E..... R.....ID 0,0-0,0} visibility = 4
    I/TestView: onVisibilityChanged(View changedView, int visibility) changedView = com.android.internal.policy.impl.PhoneWindow$DecorView{3aeb2b95 V.E..... R.....ID 0,0-0,0} visibility = 0
    I/TestView: onAttachedToWindow()
    I/TestView: onWindowVisibilityChanged(int visibility) visibility = 0
    I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = true

    销毁

    I/TestView: onWindowFocusChanged(boolean hasWindowFocus) hasWindowFocus = false I/TestView: onWindowVisibilityChanged(int visibility) visibility = 8 I/TestView: onDetachedFromWindow()

    下面比较下LinearLayout和RelativeLayout的性能

    一个实现垂直列表的布局测试数据如下:

    LinearLayout

    Measure:0.738ms
    Layout:0.176ms
    draw:7.655ms

    RelativeLayout

    Measure:2.280ms
    Layout:0.153ms
    draw:7.696ms

    考虑到误差,两者layout和draw几乎差不多,主要区别在于Measure。

    1、分析源码发现,在RelativeLayout中,由于布局可以是B横向依赖A,A横向依赖B, 所以,Measure中会被Measure两次,一次是横向的Measure,一次是纵向。

    而在LinearLayout中,在测量之前就判断了是横向还是纵向布局。

    @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            if (mOrientation == VERTICAL) {
                measureVertical(widthMeasureSpec, heightMeasureSpec);
            } else {
                measureHorizontal(widthMeasureSpec, heightMeasureSpec);
            }
        }
    

     2、但是在Linearlayout中如果设置weight会影响性能,因为LinearLayout会避开设置过weight属性的view做第一次measure,完了再对设置过weight属性的view做第二次measure。

    3、view中的Measure有个优化,但是如果RelativeLayout中设置的margin就会跳过这个优化,多以尽量使用padding而不是margin。

    4、

    .在不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout。
    最后再思考一下文章开头那个矛盾的问题,为什么Google给开发者默认新建了个RelativeLayout,而自己却在DecorView中用了个LinearLayout。因为DecorView的层级深度是已知而且固定的,上面一个标题栏,下面一个内容栏。采用RelativeLayout并不会降低层级深度,所以此时在根节点上用LinearLayout是效率最高的。而之所以给开发者默认新建了个RelativeLayout是希望开发者能采用尽量少的View层级来表达布局以实现性能最优,因为复杂的View嵌套对性能的影响会更大一些。

    参考:
    作者:尹star
    链接:http://www.jianshu.com/p/8a7d059da746
    作者:周君宜
    链接:http://www.jianshu.com/p/08e6dab7886e
  • 相关阅读:
    Iconfont在Vue中的使用
    yarn安装依赖报错
    动漫
    伤痛的魅力。绷带男子特辑
    记STM32F103C8T6+STLINK下载器在Keil中的设置
    JQuery浮动对象插件
    树莓派RTL8723BU_LINUX驱动安装
    python虚拟环境相关设置备忘
    解决树莓派控制台命令行乱码
    python模块wifi使用小记
  • 原文地址:https://www.cnblogs.com/SA226343/p/7251044.html
Copyright © 2020-2023  润新知