Android 性能优化典范笔记

1.尽量避免Overdraw.
1).移除非必须的background.
2).减少重叠的布局
3).可以通过canvas.clipRect()来帮助系统识别那些可见的区域。
这个方法可以指定一块矩形区域,只有在这个区域内才会被绘制,其他的区域会被忽视。
这个API可以很好的帮助那些有多组重叠组件的自定义View来控制显示的区域。
同时clipRect方法还可以帮助节约CPU与GPU资源,在clipRect区域之外的绘制指令都不会被执行,
那些部分内容在矩形区域内的组件,仍然会得到绘制。
除了clipRect方法之外,我们还可以使用canvas.quickreject()来判断是否没和某个矩形相交,从而跳过那些非矩形区域内的绘制操作。
4).逐步对数据进行过滤筛选,减小搜索的数据集,以此提高程序的执行性能.


2.避免出现内存抖动.
内存抖动是因为大量的对象被创建又在短时间内马上被释放。
瞬间产生大量的对象会严重占用Young Generation的内存区域,当达到阀值,剩余空间不够的时候,也会触发GC。
即使每次分配的对象占用了很少的内存,但是他们叠加在一起会增加Heap的压力,从而触发更多其他类型的GC。
这个操作有可能会影响到帧率,并使得用户感知到性能问题。
你需要避免在for循环里面分配对象占用内存,需要尝试把对象的创建移到循环体之外,
自定义View中的onDraw方法也需要引起注意,每次屏幕发生绘制以及动画执行过程中,
onDraw方法都会被调用到,避免在onDraw方法里面执行复杂的操作,避免创建对象。
对于那些无法避免需要创建对象的情况,我们可以考虑对象池模型,通过对象池来解决频繁创建与销毁的问题,
但是这里需要注意结束使用之后,需要手动释放对象池中的对象。


3.避免出现内存泄漏.
1).避免使用异步回调.
2).避免使用 static 对象.
3).避免把View添加到没有清除机制的容器里面


4.减少透明区域对性能的影响
通常来说,对于不透明的View,显示它只需要渲染一次即可,可是如果这个View设置了alpha值,会至少需要渲染两次。
原因是包含alpha的view需要事先知道混合View的下一层元素是什么,然后再结合上层的View进行Blend混色处理。
我们可以通过setLayerType的方法来指定View应该如何进行渲染,从SDK 16开始,我们还可以使用ViewPropertyAnimator.alpha().withLayer()来指定.

5.设置图片解码率


6.对bitmap做缩放,避免分配不必要的内存。


7.使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,
新解码的bitmap会尝试去使用之前那张bitmap在heap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放bitmap。
利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小。


8.使用ArrayMap
ArrayMap的插入与删除的效率是不够高的,
满足下面2个条件的时候才考虑使用ArrayMap:
1.对象个数的数量级最好是千以内
2.数据组织形式包含Map结构

9.自动装(拆)箱
为了避免HashMap的autoboxing行为,Android系统提供了SparseBoolMap,SparseIntMap,SparseLongMap,LongSparseMap等容器。
使用场景也和ArrayMap一致,需要满足数量级在千以内,数据组织形式需要包含Map结构。

10.避免使用 enum
使用 常量 代替.(https://noobcoderblog.wordpress.com/2015/04/12/java-enum-and-android-intdefstringdef-annotation/)


11.布局性能问题

RelativeLayout 会发生两次 layout 操作(在确定每个子 view 位置的时候,需要给所有的子 view 进行排序,所以需要纵向横向分别进行一次测量排序),

LinearLayout 在设置了 weight 属性后也会触发两次 layout 操作(如果不使用 weight 属性,LinrarLayout 会在当前方向上进行一次 measure 的过程,如果使用weight属性,LinearLayout 会先对没有设置过 weight 属性的子 view 做第一次 measure,然后再对设置过 weight 属性的子 view 进行第二次measure).

在任何时候都请避免调用 requestLayout() 的方法,因为一旦调用了 requestLayout,会导致该 layout 的所有父节点都发生重新layout的操作。


12. 减小应用程序安装包的大小
1).使用 Proguard 工具来帮助应用程序对代码进行瘦身
2).确保在 build.gradle 文件中开启了 minifEnabled 与 shrinkResources 的属性,
这两个属性可以帮助移除那些在程序中使用不到的代码与资源,帮助减少APP的安装包大小。
3).有选择性的提供对应分辨率的图片资源,系统会自动匹配最合适分辨率的图片并执行拉伸或者压缩的处理。
4).在符合条件的情况下,使用Vertor Drawable替代传统的PNG/JPEG图片,能够极大的减少图片资源的大小。
传统模式下,针对不同dpi的手机都需要提供一套PNG/JPEG的图片,而如果使用Vector Drawable的话,只需要一个XML文件即可。
5).尽量复用已经存在的资源图片,使用代码的方式对已有的资源进行复用(将图片进行旋转操作).

13.Removing unused resources


14.不要在任何非UI线程里面去持有UI对象的引用。
系统为了确保所有的UI对象都只会被UI线程所进行创建,更新,销毁的操作,
特地设计了对应的工作机制(当Activity被销毁的时候,由该Activity所触发的非UI线程都将无法对UI对象进行操作,否者就会抛出程序执行异常的错误)
来防止UI对象被错误的使用。


15.GPU 渲染
Swap Buffers:对应原先Process(橙色),表示处理任务的时间,也可以说是CPU等待GPU完成任务的时间,线条越高,表示GPU做的事情越多;
Sync & Upload:通常表示的是准备当前界面上有待绘制的图片所耗费的时间,为了减少该段区域的执行时间,
我们可以减少屏幕上的图片数量或者是缩小图片本身的大小。
Measure & Layout:这里表示的是布局的onMeasure与onLayout所花费的时间,一旦时间过长,
就需要仔细检查自己的布局是不是存在严重的性能问题。
Animation:表示的是计算执行动画所需要花费的时间,包含的动画有ObjectAnimator,ViewPropertyAnimator,Transition等等。
一旦这里的执行时间过长,就需要检查是不是使用了非官方的动画工具或者是检查动画执行的过程中是不是触发了读写操作等等。
Input Handling:表示的是系统处理输入事件所耗费的时间,粗略等于对于的事件处理方法所执行的时间。
一旦执行时间过长,意味着在处理用户的输入事件的地方执行了复杂的操作。
Misc/Vsync Delay:如果稍加注意,我们可以在开发应用的Log日志里面看到这样一行提示:
I/Choreographer(691): Skipped XXX frames! The application may be doing too much work on its main thread。
这意味着我们在主线程执行了太多的任务,导致UI渲染跟不上vSync的信号而出现掉帧的情况。


原文: http://hukai.me/android-performance-patterns/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值