Android性能优化总结

一、性能优化的意义

        很多时候都在忙于业务的开发,根本没有时间估计代码质量,业务架构设计,类的职责划分,设计模式的选型等,久而久之,代码的可读性、可维护性越来越差,所以强制code review机制,强制开发阶段注重代码的质量。代码的质量直接决定了APP的质量,直接决定了APP操作的流畅性,APP运行的稳定性。流畅性和稳定性是提供用户留存率,转化率的关键。

二、优化原则

不能为了优化而优化

  • 权衡利弊:在能够保证产品稳定、按时完成需求的前提下去做优化
  • 使用低配置的设备:同样的程序,在低端配置的设备中,相同的问题会暴露的更为明显
  • 评估性能优化的效果,应该保持足够多的测量,用数据说话(使用各种性能工具测试及快速定位问题)

三、优化方法

  • 了解问题(分为可感知和不可感知的性能问题):对于性能问题来讲,这个步骤只适用于某些明显的性能问题,很多无法感知的性能问题需要通过工具定位。例如:内存泄漏、层级冗杂、过度绘制等无法感知。滑动卡顿是可以感知到的。
  • 定位问题:通过工具检测、数据分析,定位在什么地方存在性能问题。
  • 分析问题:找到问题后,分析针对这个问题该如何解决,确定解决方案,
  • 解决问题:根据分析结果寻找解决方案。
  • 验证问题:保证优化有效,没有产生新的问题,以及产品稳定性,输出一份优化前后的对比数据

四、性能优化四个方向

        性能问题的主要原因有相同的,也有不同的,但归根到底,不外乎内存使用、代码效率、合适的策略逻辑。代码质量、安装包体积这一类问题。

想要达到高质量的应用需要从四个方向出发:

  • 操作流畅,使用时避免出现卡顿,响应速度快,减少用户的等到事件,满足用户期望
  • 运行稳定,减少crash率,不要在用户使用过中出现崩溃和无响应
  • :省内存,省流量,省电量,较少用户的使用成本,避免使用时导致手机发烫
  • :安装包小可以降低用户的安装成本

五、流畅性优化方向

优化原因:利于减少使用中的卡顿,响应时间久的问题,给用户一个操作流畅的体验

优化方向:主要针对3个方面的优化:启动速度优化、页面显示速度,事件响应速度

页面显示速度

  • 页面显示慢的原因:
    • 页面绘制的内容(布局&控件)太多,从而导致页面测量时间过长
    • 绘制效率过低,从而导致绘制时间过长
  • 优化方案:
    • 布局层级优化
      用约束布局替代嵌套的线性布局,铺平布局,在复杂的布局中效果明显
    • 异步加载xml
      使用AnyscInflate异步布局解析器来解析xml文件,从而释放主线程的压力
    • 离屏预渲染
      比如首页数据和列表上所需要的view,可以在启动阶段就使用线程提前预加载缓存和数据,并创建缓存的view放在一个viewpull当中,进入首页列表之后直接从viewpull拿出预先加载好的view交给recycleview,在首页秒开里效果明显

启动速度优化

  • 启动速度慢的原因:初次打开应用时,大量初始化任务或者需要加载很多资源
  • 优化方案
    • 异步并发初始化
    • 异步初始化,延时初始化的策略,减少启动应用时加载的任务,从而提高启动速度

响应速度优化

应用程序出现响应慢的情况,会出现ANR

  • 优化原因
    • 在5s内未响应用户的输入事件(按键、触摸输入),在10s内未处理完BroadcastReceiver接收的事件,在20s内未处理完Service接收到的事件
    • 多线程锁竞争,线程的休眠与唤醒是会占用CPU的一部分资源,如果资源不够用,此时就会主线程卡顿
    • 主线程阻塞、挂起、死循环、执行比较长的耗时操作、其他子线程对CPU的占用率过高,导致主线程抢不到CPU时间片
  • 优化方案
    当发生ANR的时候,ActivityManagerService会把ANR信息写到LogCat日志中,还会写入到/data/anr/traces.txt文件中,主要通过ANRManager,ActivityManager等字段在LogCat日志中过滤出关键信息
    线上阶段可以使用爱奇艺开源的xcrash:可以收集java、native、anr的错误信息,实现方式都是通过c++来实现的,原理:当Android系统发生anr crash后,并发出相应的信号量,在c++层面去注册这个信号量,在回调里区down出堆栈信息

关键信息:
 

ANR in (Process Name)【Shot Component Name】:ANR发生在哪个进程,哪个包/类里,定位到类

PID:应用程序进程ID

Reason ANR:发生ANR的原因:

  • Input dispatching timed out :输入事件引起的ANR 
  • ExecutingService:Service执行任务引起的ANR
  • Broadcast of:广播引起的ANR

Process CPU state:分析各进程的时间占用率,来判断某些进程是否长期占用CPU过高,导致应用进程获取不到足够的CPU处理时间,而发生ANR,比如:各进程总的CPU占用率,用户CPU时间占用率,系统CPU时间占用率,iowaitCPU时间占用率

六、内存优化

在内存优化的原因:

        由于APP在运行时可以申请到使用的内存是有上限的,如果内存使用不合理,APP运行时,响应速度就是变慢,在后台运行时也是很容易被后台系统回收掉的,内存的不合理使用时看不到的,只能通过感受到滑动不顺畅了,点击响应不及时,但这并不一定就是这一块代码引起的

在做内存优化前,需要了解应用的内存的使用现状,通过现状去分析哪些数据类型有问题,各种类型的分布情况如何,以及在发现问题后是哪些具体对象导致的,这就需要借助相关工具

Memory Profiler

在Android studio中的tools-profiler中可查看 

可视化工具,可以清晰的观察应用运行时,实时内存的使用情况:

  • 内存抖动
  • 内存占用趋势
  • 内存泄漏链路
    路径分析,不够简洁,不够清晰,

Memory Analyzer Tool (MAT)

MAT 是一个快速,功能丰富的 Java Heap 分析工具,通过分析 Java 进程的内存快照 HPROF 分析,从众多的对象中分析,快速计算出在内存中对象占用的大小,查看哪些对象不能被垃圾收集器回收,并可以通过可视化视图直观地查看可能造成这种结果的对象。

常见内存泄漏场景

        内存泄漏之后再去找原因再去修复会增加开发成本,所以最好的解决方案是在编码阶段就考虑到内存使用问题,写出高质量代码

  • 资源性对象未关闭
    比如Cursor、File文件等,往往都用了一些缓冲,在不使用时,应该及时关闭它们

  • 注册对象未注销
    比如事件注册后未注销,会导致观察者列表中维持着对象的引用

  • 单例引用短生命周期对象

  • 非静态内部类的静态实例

  • Handler临时性内存泄漏
    如果Handler是非静态的,容易导致 Activity 或 Service 不会被回收

  • WebView
    WebView 存在着内存泄漏的问题,在应用中只要使用一次 WebView,内存就不会被释放掉。

优化内存空间

        没有内存泄漏,并不意味着内存就不需要优化:在移动设备上,由于物理设备的存储空间有限,Android 系统对每个应用进程也都分配了有限的堆内存,因此使用最小内存对象或者资源可以减小内存开销,同时让GC能更高效地回收不再需要使用的对象,让应用堆内存保持充足的可用内存,使应用更稳定高效地运行。

  • 对象引用关系
    强引用、软引用、弱引用、虚引用四种引用类型,根据业务需求合理使用不同,选择不同的引用类型
  • 减少不必要的内存开销
    注意自动装箱,增加内存复用,比如有效利用系统自带的资源、视图复用、对象池Bitmap对象的复用
  • 使用最优的数据结构
    比如针对数据类容器结构,
    可以使用ArrayMap、SparseArray数据结构,数据查找速度比HashMap要高,内存占用率比HashMap也要高,因为他们数据在存储时不会存在自动装箱的问题。
    避免使用枚举类型,
    使用缓存时除了linkedHashMap,还有LruCache
    删除插入比较多的可以使用链表,查找比较多的可以使用Map、ArrayMap
  • 图片内存优化
    设置位图格式压缩,用一些图片缓存方式对图片进行管理,使用图片压缩比比较高的图片格式,比如矢量图、opt,在做图片加载时可以配合cdn裁剪的能力,已经本地缓存的能力

七、稳定性优化

Android 应用的稳定性定义很宽泛,影响稳定性的原因很多,比如内存使用不合理、代码异常场景考虑不周全、代码逻辑不合理等,都会对应用的稳定性造成影响。其中最常见的两个场景是:Crash,这个错误将会使得程序无法使用,比较常用的解决方式如下:

  • 提高代码质量
    关键在于建立强有力的code review机制,比如开发期间的代码审核,看些代码设计逻辑,业务合理性
  • 代码静态扫描工具
    常见工具有Android Lint、Findbugs、Checkstyle、PMD
  • Crash监控
    把一些崩溃的信息,异常信息及时地记录下来,以便后续分析解决
  • Crash上传机制
    在Crash后,量先保存日志到本地,然后等下一次网络正常时再上传日志信息

八、流量优化

流量优化针对于下沉市场的用户意义重大,他们不都是无线连接,无线流量。减少数据量也可以加快页面渲染速度

  • 主要通过 缓存 减少网络流量,采用三级缓存方案:即 内存缓存-硬盘缓存-cdn
  • 升级http协议到http2.0
    http2.0协议中对header部分的数据做了大幅度的压缩,同时对body部分使用了二进制的分帧,多路传输,无论是流量还是效率都比Http1.1快的多
  • 打包网络请求
    一个页面中如果存在多个接口的请求,可以让服务端将这些接口请求组合起来,弄成一个接口去请求就可以了
  • 调整数据传输
    可以根据不同的网络状态,接口返回的 response的数据可以是不同的,比如在wifi下可以返回40条,5G可以返回30条,4G下返回20条等等,可以使用protobuf协议进行传输数据
  • IP直连与HttpDns
    Http在传输过程中,其中一步是拿到域名去找主机IP,才能建立起一个链接,这个过程是到运行商的DNS服务器上去查询的,现在主流的做法使用大厂自建的HttpDns,在全国多个重点地区建立了DNS的查询服务,这样通过域名去查找IP的耗时会大大的减少,从而加快Http链接的建立
  • 大文件处理断点续传
    在下载文件时可以采用断点续传,或者是增量更替的方式
  • 数据上传时压缩
    在做埋点数据的上传,或者表单提交时,可以考虑body部分的数据进行二级制压缩,从而降低数据传输量

除了使用抓包工具Charls等查看之后,也可以使用Android studio里面的自带的Network profile这个工具来查看APP运行时流量消耗情况,可以直观的观看request、response的响应情况,以及数据的体积和大小

九、安装包大小体积优化

        应用安装包大小对应用使用没有影响,但应用的安装包越大,用户下载的门槛越高,特别是在移动网络情况下,用户在下载应用时,对安装包大小的要求更高,因此,减小安装包大小可以让更多用户愿意下载和体验产品

Apk文件的组成:

  • assets/ :存放配置文件、资源文件,assets不会自动生成对应的ID,而是通过AssetManager 类的接口获取
  • res/  这个目录存放资源文件,会自动生成对应的ID 并映射到R.java 文件中,访问直接使用资源 ID
  • lib/  保存应用的so文件 或者jar包
  • AndroidManifest.xml  这个文件用来描述 Android 应用的配置信息,一些组件的注册信息、可使用权限等
  • classes.dex 虚拟机可执行的字节码程序
  • resources.arsc 资源文件和资源 ID 之间的映射关系,用来根据资源 ID 寻找资源文件

注意:res下的资源文件、lib下面的so文件、dex资源文件,是重点优化的方向

减少安装包大小的常用方案:

  • 资源优化:尽可能减少不必要的(图片,xml)文件
    择内存占用小的图片格式矢量图vector-->webp--jpeg-->png
    借助TinyPng的能力对图片资源文件进行压缩,可以开发一款TinyPng的插件,在打release包之前主动对png图片资源进行自动化压缩
  • 单ABI架构:打包时JniLibs下面只存放一种类型的SO文件
    使用apk-analyse-tool参考国民应用ABI架构选项
    根据打点统计用户设备CPU架构的类型,决定包集成ABI的类型
  • so文件动态加载:不常用的so文件不跟包发布
    根据业务埋点,决定那些SO文件可以动态下载
  • 代码混淆:混淆之后原有的字符串,类路径都会被压缩
    开启minifyEnabled
  • 动态化框架:dinamicX--weex--h5
    根据业务场景选择合适的动态化技术框架,页面代码可动态下发,不必跟包发布

10、总结

        性能优化不是更新一两个版本就可以解决的,是持续性的需求,持续集成迭代反馈。在实际的项目中,在项目刚开始的时候,由于人力和项目完成时间限制,性能优化的优先级比较低,等进入项目投入使用阶段,就需要把优先级提高,但在项目初期,在设计架构方案时,性能优化的点也需要提早考虑进去,这就体现出一个程序员的技术功底了。
        什么时候开始有性能优化的需求,往往都是从发现问题开始,然后分析问题原因及背景,进而寻找最优解决方案,最终解决问题,这也是日常工作中常会用到的处理方式。

        重在预防,贵在治理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值