浅谈android布局UI优化

写在开头

浅谈android内存优化

我网没问题啊,界面怎么卡啊?
其实有时候,界面写的不好也比较容易发生卡顿且导致应用占用大量内存。如果你的app真的发生了,很遗憾这一定会影响用户体验。
在学习的过程中,看了很多大神的学习资料,在这里总结一下。帮助自己,也传播一下。

卡顿罪魁祸首

其实我们眼中的卡顿,就是android在界面渲染的时候丢帧了。 Android系统要求每一帧都要在 16ms 内绘制完成,在这个时间内你的界面就是流畅的(能够达到流畅的画面所需要的60fps)
PS:记得大学玩lol时,fps低于60画面就会特别卡,原来如此。
这里写图片描述
我没有忽悠你们哦,不信你们试试。跑题了感觉哈哈。
假设你花了大于16ms的时间来绘制这一帧,那么就会出现掉帧的情况。反馈到用户身上,就是界面卡了,不流畅了。

丢帧的各种原因:

  • layout 太过复杂,层次过多,UI 上有层叠太多的绘制单元,过度绘制
  • CPU 或者 GPU 负载过重
  • 动画执行的次数过多(简单的说就是一大堆动画重复了一遍又一遍,消耗 CPU 、 GPU 资源)
  • 频繁 GC,主要是内存抖动
  • UI 线程执行耗时操作(所以要放在子线程执行好使操作)

分析与建议解决

Layout 太过复杂,层次过多,UI 上有层叠太多的绘制单元,过度绘制

对于我们layout文件,层级越多,android在初始化他们时,也就是渲染时就越浪费时间。所以布局的优化其实说白了就是减少层级,越简单越好,减少overdraw( 过度绘制是一个术语,表示某些组件在屏幕上的一个像素点的绘制次数超过 1 次。),就能更好的突出性能。

常用布局大解析:

LinearLayout和RelativeLayout 性能大比拼:

LinearLayout 在 measure 的时候,在横向或者纵向会去测量子 View 的宽度或高度,且只会测量一次。但是当设置 layout_weight 属性的时候会去测量两次才能获得精确的展示尺寸。


RelativeLayout 在 measure 的时候会在横向和纵向各测量一次。也就是需要两次度量来确保自己处理了所有的布局关系。

高能:

如果带有 weight 属性的 LinearLayout 或者 RelativeLayout 被套嵌使用,measure 所费时间可能会呈指数级增长(两个套嵌的叶子 view 会有四次 measure,三个套嵌的叶子 view 会有8次的 measure)。为了缩短这个时间,保持树形结构尽量扁平(深度低),而且尽量要移除所有不需要渲染的 view。

那么我们给怎样使用这两个布局呢:告诉你,视情况而定。

  • 尽量避免在视图层级的顶层使用相对布局 RelativeLayout 。相对布局 RelativeLayout 比较耗资源,因为一个相对布局 RelativeLayout需要两次度量来确保自己处理了所有的布局关系。
  • 布局层级一样的情况建议使用线性布局 LinearLayout 代替相对布局 RelativeLayout,因为线性布局 LinearLayout 性能要更高一些;
  • 当LinearLayout 需要嵌套才能实现的复杂布局,建议使用RelativeLayout
  • 尽量避免使用 layoutweight 属性。(但是的确在等分布局时挺好用的,你说是不是,哎,我承认我在用)

其他布局优化

  • include标签 (引入布局)
  • merge标签(简单粗暴点回答:干掉一个view层级。主要作用是为了防止在引用布局文件时产生多余的布局嵌套)
  • ViewStub标签(一句话总结:高效占位符。ViewStub是View的一种,但是它没有大小,没有绘制功能,也不参与布局,资源消耗非常低。主要作用是把我们不常用的view在我们需要的时候才去加载)

注意:如果你这上面三个布局不知道,别告诉我你是android的,让ios笑话。哎,我这么善良。那么郭霖大神你应该知道吧,给你http://blog.csdn.net/guolin_blog/article/details/43376527

  • Android最新的布局方式ConstaintLayout(其实人家ios早就使用了,也就是拖拽布局)

    ConstraintLayout允许你在不适用任何嵌套的情况下创建大型而又复杂的布局。它与RelativeLayout非常相似,所有的view都依赖于兄弟控件和父控件的相对关系。但是,ConstraintLayout比RelativeLayout更加灵活,目前在AndroidStudio中使用也十分方便。
    

本文只谈优化,不谈使用,想学习的话,去吧,皮卡丘 http://blog.csdn.net/jdsjlzx/article/details/51460581

过度绘制:过渡绘制是一个术语,表示某些组件在屏幕上的一个像素点的绘制次数超过 1 次。过度绘制导致的问题是花了太多的时间去绘制那些堆叠在下面的、用户看不到的东西,浪费了 CPU 周期和渲染时间。

优化:

  • 去除重复或者不必要的 background
  • 点击态中的 normal 尽量设置成 transparent
  • 去除 window 中的 background(这个可以通过处理 decorView 或者设置 Theme 的方式)

CPU 或者 GPU 负载过重

UI 线程是应用的主线程,很多的性能和卡顿问题是由于在主线程中做了大量的工作。除了主线程外,子线程占用过多 CPU 资源也会导致渲染性能问题。

在 UI 渲染的过程中,是 CPU 和 GPU 共同合作完成的,其中 CPU 负责把 UI 组件计算成 Polygons,Texture 纹理,然后交给 GPU 进行栅格化渲染。如果您在主线程做了耗时的操作,简单的会造成界面的卡顿,严重的直接anr了。

各界面耗时操作anr时间对比:

  • 主线程:5秒
  • 广播接收者:10秒
  • 服务:20s

频繁GC

如果您频繁创建大对象或者频繁创建大量对象,并且这些对象属于用完就废弃的。那么恭喜您,这可能会导致内存抖动的问题。

其实也没啥好用的办法

    一个大神说的:其实也挺好理解
    大对象可以使用对象池复用,比如 byte[]
    尽量在 16ms 内少创建对象,比如在 onDraw 中创建 Paint 对象,decode Bitmap 之类的

其他优化

如果是一些简单的图片,写shape吧,别让美工切图了!
如果是可拉伸的图片背景,用draw9patch吧,如果您不会,请你移步
http://blog.csdn.net/leeccncdl/article/details/7303635/

写在最后

感谢大神在学习的路上帮我们走出一条路。
http://blog.csdn.net/jdsjlzx/article/details/51460581
http://www.cnblogs.com/hoolay/p/6248514.html
http://blog.csdn.net/guolin_blog/article/details/43376527
http://www.jianshu.com/p/145fc61011cd
http://yydcdut.com/2017/03/10/ui-optimize/

猜你喜欢

转载自blog.csdn.net/say_from_wen/article/details/77994245