App性能优化分类
我们在App的迭代过程中,经常要进行App的优化。App优化是一个非常广的概念。设计到App的各个方面。在平时开发过程中,我主要接触到,卡顿优化、内存优化、网络优化、代码优化等方面。下面也仅仅从我自己搞过的一些方面纪录下App中遇到的各种优化问题,加深自己的记忆。
一. 卡顿优化
首先我们要明确造成卡顿的原因,Android系统每隔16ms发出VSYNC信号,触发对UI的渲染,16ms没完成绘制就会卡顿。造成卡顿的原因是多方面的,在排除客观因素外(手机年代久远等),我们主观上能解决的主要包括两个方面。 1)布局嵌套的层次太深 2)feed流中加载的图片太大,导致系统不停的触发gc,导致卡顿。
1)布局嵌套的层次太深##
这方面,程序员应在设计界面的时候,尽量使布局的层次不要太深。关于布局的层次可以从开发者选项中显示过度绘制区域打开。颜色标识: GPU过渡绘制从好到差:蓝-绿-淡红-红 。
蓝色1x过度绘制
绿色2x过度绘制
淡红色3x过度绘制
红色超过4x过度绘制
a. 利用Hierarchy Viewer 得到整体的布局图,通过观察相关的属性查看是否有冗余的layout。
b. setContentView(R.layout.XXX) 一般都会存在至少两层的绘制,一层是窗口window的绘制,一层是布局的背景(如果存在背景的话)。如果是这种情况,可以将这个window背景去掉,这个背景的重绘是系统级别的,和主题有关,通过getWindow().setBackgroundDrawableResource(android.R.color.transparent)去除窗口的绘制即可。
c. 使用merge标签和 ViewStub标签
d. 通过RelativeLayout 和FrameLayout 代替Linearlayout 减少布局层次 。 在相同的布局层次下,通过Linearlayout 和FrameLayout 代替 RelativeLayout 优化 RelativeLayout 两次OnMeasure的开销。
2)feed流中加载的图片太大##
一般公司都会有CDN服务器,我们的图片资源会上传到CDN中。我们应该保证上传到CDN的图片尺寸,使客户端下载冰显示的图片不会太大。同时,我们要选择优秀的图片库,比如说,Glide、Picasso、Fresco 等。我们在使用图片库的时候尽量对下载的图片做压缩,使加载到内存的图片不至于很大。也不会导致平凡的GC导致的卡顿。关于具体的图片优化部分,我将在下文的内存优化之图片优化时具体的给出。
二. 内存优化
关于介绍的废话我就直接省略了,我们直接接入主题。内存优化中我接触到的比较多的地方,主要分为2类。1)内存泄露 ,2)图片相关
1)内存泄露##
a. 单例导致的内存泄露,如单例中传一个Activity,那么在App运行期间,这个单例会一直持有Activity的引用,导致Activity无法释放。解决方案为,多数情况下可以用Application的Context来替换Activity。
b. 静态变量导致的内存泄露,如静态变量中的Context,应该杜绝这种写法。
c. 非静态内部类导致的内存泄露,非静态内部类可以引用外部的成员,这也是内存泄露的元凶。应尽量使用静态内部类。
d. 设计和使用观察者模式时,尽量增加unRegister 方法,并在页面关闭时反注册。
e. 动画及时关闭,特别是无限循环的动画。
f. Handler 导致的内存泄露,在App中尽量不要直接使用系统的Handler, 我们应该创建具有弱引用功能的Handler,可以对Callback使用弱引用。
2)图片相关##
但凡是有feed流的App,都不可避免的和本地图片和网络图片打交道。图片的大小,尺寸对内存的影响非常大。这一点大家可以去搜索一下, bitmap 占内存大小 = 图长 * 图宽 * 每个像素占用的字节数。png中是ARGB_8888格式,一个像素占用8字节。
a. 占位图优化,一个App中尽量使用一张占位图,并制作成 9 patch格式图片。设置占位图时,尽量使用图片库中的设置方式,比如Picasso中设置占位图是以src形式设置的,而不是以background形式设置的。设置background形式的占位图可能会导致过度绘制的风险(当src不能盖住background时,会多绘制一层,例如ImageView设置了padding)。
b. 网络图片压缩,使用Picasso时,尽量调用它的resize()方法。这样保存在内存缓存中的图片是经过压缩变换的。使用Glide时可以省去这些烦恼。此外Glide中变换后的图片保存的是RGB_565格式,一个像素占用2字节,Picasso中是ARGB_8888格式,一个像素占用8字节。相同的一张图,Picasso中占用的内存是Glide的4倍。
c. 对于本地图片可以使用tinyPng进行压缩,大家要是感兴趣,我可以奉献一个插件帮助大家使用tinyPng自动压缩图片资源。
d. 使用webp代替png,对于网络图片库,可以参考Fresco的webp解析模块,既可以解析webp静态图,也可以解析webp动画。节省一半以上的流量。
三. 网络优化
在Android平台上,网络优化可以节省电量、给用户节约流量。提高应用的反应速度。具体的优化措施有:
a. 使用Ip直连的方案来避免DNS解析。此外,为了应对IP的变化。因此IP需要增加动态更新能力,定时的从服务器获取最新的IP。当IP访问失败时,增加容错机制,切换到域名访问方式上来。
b. 不同网络环境切换时,动态改变线程池的大小。这一点 Picasso 和 其它的网络库都会有类似的设计。
c. 使用gzip压缩网络数据
d. 本地要使用线程时,可以建立公共的线程池。便于线程的统一管理。
四. 代码优化
在不是很小的公司都有review代码的环节,review代码的目的就是要去监督大家按照约定好的编码规范去写代码。其次,写代码时类的注释和公共方法的注释一定要加的比较详细。这样交接时,别人才不会那么难受。再说了,写代码时,都把自己的身份放在类注释上面了。不好好写注释,就不担心后面的人骂吗。
此外,要保持良好的习惯。在联调阶段,扫一遍lint,把无效的资源和图片文件,把无效的类给删除了。永远不要想着,这些类以后会用到,好的产品经理是不会吃回头草的。