Android性能优化总结

前言

在Android进阶之路上, 性能优化是一个绕不开的问题。这部分内容非常考验程序员的内功和项目经验,必须要对Android各功能模块原理和Android系统有个比较全面的了解才能做好这个工作。

本人在前段时间的工作中做过一些优化,现在把这部分内容做个简单的总结,分享给大家。由于时间关系,先简单总结一下,至于各部分的细节,后面再写吧。

我的优化工作主要包含了以下部分:UI优化内存优化apk优化网络优化、多线程、数据存储优化

性能优化.png

一、UI优化

关于UI优化,其实主要是UI卡顿的优化。卡顿本质:Android系统大概每隔16ms会做一次屏幕刷新,如果一次UI渲染不能在这个时间范围内完成,那么将会出现丢帧的现象,从而产生卡顿。

面试官:说说Android的UI刷新机制?
Android 屏幕刷新机制
Android进阶——性能优化之布局渲染原理和底层机制机详解及卡顿根源探究(四)

如果面试问了UI卡顿相关的问题,虽然会要求你说一些导致卡顿的原因(过度绘制、布局嵌套太深等),但这只是表象,有经验的面试官可能更多的是想听你讲一下Android屏幕渲染机制,所以这里简单说一下屏幕渲染,更详细的内容可以参考上面几篇文章。

Android屏幕刷新机制简介

首先屏幕系统主要包括CPU、GPU、屏幕显示器三个部分,CPU(中央处理器)主要负责数据计算,GPU(图像处理器)负责图片渲染,屏幕显示器负责最后的显示。Android中的UI绘制逻辑大概是:CPU负责View树的遍历(measure、layout、draw),然后把计算好的数据交给GPU,告诉GPU在屏幕什么位置如何绘制图形,GPU对数据渲染,渲染好后放到buffer里存起来,交给显示器,显示器负责把buffer里面的数据显示到屏幕上。

注意:我们常说的 Android 每隔 16ms 刷新一次屏幕其实是指:底层以固定的频率,比如每 16ms 将 buffer 里的屏幕数据显示出来。但是这不代表就一定会去执行onDraw()方法,onDraw()方法必须要主动触发才会执行,如果没有的话,当下一次刷新信号来临的时候,显示器就拿着buffer里面旧的数据去显示,而不是说去执行View树的重绘。

1.1 View过度绘制

View过度绘制,是指某些像素在同一帧时间内被绘制多次,从而使CPU或GPU负载过重。这个问题很常见,在布局的ViewGroup嵌套中,稍不注意就出现这种问题,检测的话可以打开守旧开发者选项-->Show GPU Overdraw查看。如果出现红色的尽量优化一下,一般不是太深的话不会卡顿的。

1.2 布局嵌套层级太深,无法在16ms内完成渲染

Android的渲染机制还是比较复杂的,但是应用层来说,主要是measure -->layout--->draw流程。UI绘制实际上是遍历View树,View树层级越深,测量布局耗费的时间就越长,那留给draw的时间就可能不够,自然就会出现丢帧卡顿。

建议:
1、尽可能用扁平化的布局ConstraintLayout;
了解使用 ConstraintLayout 的性能优势
2、合理利用includemerge来减少布局层次

1.3 刷新不合理

建议:减少刷新次数、缩小刷新区域;

1.4 频繁触发measure、layout、draw

浪费CPU、GPU

1.5 主线程做了稍微耗时的操作

比如说读取一下SharedPreference、json反序列化,读取一下文件这些,如果累加时间多了也会丢帧。

1.6 GC频繁

短期内大量垃圾对象的创建、回收会导致频繁gc,主要是循环里面创建对象会导致这种现象,还有一种情况,在自定义view的onDraw()方法创建大量对象,如果onDraw()调用频率很快,和循环没什么区别,在里面创建很多对象,就会发生短时间内大量对象创建并释放,于是频繁GC就发生了,内存抖动了,卡了。

Android性能优化-检测App卡顿

二、内存优化

内存优化主要是:内存泄漏、内存抖动、OOM问题。

2.1 内存泄漏

android上的内存泄漏主要是堆内存的泄漏,最常见的就是Activity泄漏。
原因:

  • jvm角度而言,主要是堆内存泄漏,分配出去堆内存没有及时回收导致;
  • 代码角度而言,不再使用的对象被其它对象所引用,导致它无法及时回收。

案例:

  • 非静态内部类、匿名内部类 Handler、Thread、AsyncTask
  • 单例模式传入Activity对象
  • 观察者模式注册之后,退出页面时没有及时取消观察
  • 资源性对象未关闭,Cursor、File等
  • WebView泄漏,放在单独进程
  • Bitmap没有及时回收,最好放在池子

分析工具
Android Studio Profile 、LeakCanary

解决思路
了解对象的gc引用链,在恰当的时机断开引用关系就可以让对象正常回收。

2.2 内存抖动

短时间内大量对象创建并释放,主要是循环里面创建大量对象,会导致频繁GC,然后内存抖动了。

2.3 OOM问题

APP启动进程之后会分配一定的内存空间,每个手机大小不同,如果程序运营期间申请的内存没有及时释放,堆积的越来越多,最好超出这个阀值就会oom,常见的有加载大图,内存泄漏导致。

常见的有:

  • 加载大图,长图;需要对bitmap压缩之后再显示,可以参考一下二次采样;
  • 资源对象使用完了没有及时回收,内存堆积也会oom;
  • 内存泄漏最严重的结果就是oom

Android避免OOM(内存优化)
深入探索 Android 内存优化(炼狱级别)

apk优化

  • res资源优化
    1、只用一套高清的图片;
    2、使用svg图片节省空间,用于小图标;
    3、使用webP图片;
    4、如果有大量的drawable.xml设置view背景,考虑用代码封装Drawable实现
    5、用Lint工具删除无用资源

  • 代码优化
    1、使用proGuard 代码混淆工具;
    2、避免引入重复的三方库;
    3、so文件只用必须的版本

Android性能优化之APK瘦身详解(瘦身73%)
深入探索 Android 包体积优化(匠心制作一)

网络优化

  • 连接复用:节省连接建立时间,如开启 keep-alive。

  • 合并请求

  • 减少传输数据的大小:对于post请求,body可以做gzip压缩的,header也可以做数据压缩。返回数据的body也可以做gzip压缩,

  • 异常拦截优化:请求失败、解析异常

  • 断点续传、分片传输、失败重连、Protocol Buffer

总结

app性能优化是一个持续总结、提升的过程;做的事情很多,但是效果不一定很明显,但你仍然需要在项目中重视此类问题。后面会持续更新

参考:

https://wetest.qq.com/lab/view/390.html
https://blog.csdn.net/huangxiaoguo1/article/details/80434456
https://segmentfault.com/a/1190000015219959
https://www.jianshu.com/p/d71b51a0e29f

你可能感兴趣的:(Android性能优化总结)