geekband android #5 第十二周分享(GC、内存优化、过度绘制等)

本文详细介绍Android应用中的垃圾回收机制及其对帧率的影响,探讨如何利用工具进行内存检测和泄漏排查,同时提供了一系列优化建议,包括视图优化、电量优化、网络优化及Wakelock优化等方面。

1.垃圾回收机制

垃圾回收器负责回收程序中已经不再使用但是仍然被各种对象占用的内存。

特点:无需手动管理内存,android系统会自动跟踪所有的对象,并释放那些不再被使用的对象。

缺点:可能会占用大量资源。


2.android中的垃圾回收机制

Young Generation       :大多数新建的对象都位于Eden区,当填满时就开始Minor GC。若存活下来的进入survivor区,但是该去仍然要进行Minor GC.

Old Generation             :存放长期村存活的对象和多次经Minor GC后依然存活的对象进行Major GC.

Permanent Generation:存放方法区,方法区中有,要加载的类信息、静态变量、final常量、属性和方法.


3.关于垃圾回收机制和FPS之间关系

当对UI进行渲染的时候整个过程在16ms中完成那么就能达到一个比较流畅的画面,60FPS。所以当GC发生在UI渲染的过程中,会增加耗时操作。

从而导致某一帧的绘制超过16ms。但是我们并不是很关注GC所用时间,更关注于GC带来的负极效果。


4.内存检测工具(重点)

Memory Monitor:内存图的每秒刷新图。

方便显示内存使用情况和GC情况

快速定位卡顿是否是GC有关

快速定位crash是否和内存使用过高有关

快速定位潜在的内存泄漏为

简单易用但是不能准确定位问题

Allocation Traker:追踪应用程序在运行时所有已创建对象及数量和它们所占用内存大小,以及它们是在那些方法中创建出来的。

定位代码中分配的对象类型、大小、时间、线程、堆栈等信息

定位内存抖动问题

配合Heap Viewer 使用定位内存泄漏问题

使用复杂

Heap Viewer:以图表形式展示运行时各对象占用内存大小、数量。(可以方便定位内存泄漏问题)

内存快照

每次GC后收集一次信息

查找内存泄漏问题

使用复杂

内存抖动:当内存突然使用很大,随后马上被GC回收而出现一个内存使用峰值,如此循环便出现多个内存使用的峰值。即是内存抖动。


5.LeakCanary(内存查找神器,难点)

支持android和java的一种查找内存泄漏的工具

使用时需要添加两个依赖:debug compile , release conpile

http://github.com/square/leakcanary


6.常见的内存泄漏

单例造成:

调用方常常会很不小心的传递一个activity进来从而被静态变量引用。使得activity不使用时本应该被回收却因为被静态变量持有而无法回收。

非静态内部类的静态实例造成:

例如,Resourse对象赋值nul,它不会被GC,但是持有当前活动。

Handler造成的内存泄漏

由于Handler经常做耗时操作,当起耗时超过Activity的时间时,本来应该被回收的Activity却因为被Handler持有而无法被GC回收。

7.视图优化

帧率和刷新率总是配合一起使用,GPU每绘制一帧、接着就在屏幕上刷新一帧。当帧率大于刷新率的时候会出现当第N-1帧刷新出来后第N帧还未绘制完毕前,紧接着就刷新第N帧。这时屏幕上半部分会刷新出第N帧而下半部份保持第N-1帧即是图片的撕裂。

为了避免这种效果,采用了双重缓冲机制。GPU在Back Buffer绘制完毕一帧然后传输给Frame Buffer,让屏幕刷新一帧。如此循环就避免了图片的撕裂。

当帧率小于刷新率的时候,会出现在刷新屏幕数据时,某两帧的图片数据是一模一样的。


8.过渡绘制:一个像素绘制超过一次

在开发者选项中打开Show GPU Overdraw选项可以追踪过度绘制。

蓝色1×过渡绘制;绿色2×过渡绘制;浅红色3×过渡绘制;深红4×过渡绘制。

还可以查看对比16ms的GPU渲染时间,如果超过16ms可能会导致不流畅,用户体验差。


9.避免UI卡顿和优化过渡绘制

避免UI卡顿

避免在onDraw中创建对象

减少View层级

避免在UI顶层使用RelativeLayout

降低自定义控件绘制的复杂度

优化过渡绘制

降低View层级,多使用RelativeLayout

去掉不必要的背景,去掉window默认背景(但注意在某些条件下可能极度影响美观,需要具体情况具体判断)。

在制作自定义控件时:dipRect&Quick Reject可使UI达到好的效果

ViewStub/.9图做背景


10.电量优化

仅有25%-30%消耗在核心功能上:画图、布局、动画。

剩下75%左右:上传统计数据、检测位置信息、轮寻服务器、拉去广告信息。


具体电量消耗:1.网络

                            2.Wakelock

                            3.非即时任务


查看电量消耗的两种方式:1.设置→电量使用情况

                                                2.使用Battery Historian

                                                             go run adb/battery-historian/battery-historian.go

                                                             $adb bugreport > bugreport.txt

                                                             localhost : 9999 

                                                             上传文件 → 选择要查看的app


11.网络优化

避免频繁的唤醒网络芯片。可以在唤醒时将网络请求打包出去

在WiFi情况下发送尽量多的网络请求(WiFi状况下耗电量小于移动网络)

避免轮寻请求

数据压缩。(这种方式可能导致客户端解压文件需要耗时操作,但仍然小于请求原文件的耗时。)


12.Wakelock优化

使用不当会使系统一直在运行中。

Active → screen off → Asleep

频繁唤醒请求导致耗电量增加。如,网络服务器挂掉了,这时如果没有一个超时判断的话,会一直执行耗时操作。


正确方法:尽量避免使用Wakelock而用AlarmManeger的 AlarmManager.setlnexact*(...)方法

                    JobSchcduler指定任意一个场景唤醒我们的操作。






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值