深入 Android 性能优化一:概要介绍

文章目录
  1. 1. 简介概况
  2. 2. 性能指标
  3. 3. 优化方案
  4. 4. 参考文献
  5. 5. 更多内容

此心不于事上磨,更于何处磨此心。

Android 的性能优化,在我们的开发,甚至是面试的过程中,是绕不开的话题。此处,虽说是初探,在这几年的开发中,或多或少对这方面有所注意和部分总结。借此机会,先谈一谈 Android 开发中性能优化的轮廓,后续也定期会有这方面的专题深入。

简介概况

我们在使用 Android 手机一段时间后,会发现手机变得有些卡顿、莫名发烫、掉电快,甚至有些应用在运行期间会崩溃掉,只得借助一些清理软件来清扫优化,以短期提高运行速度。实际上,看硬件配置,Android 设备不输于 iOS 设备,造成以上现象的原因大致如下:

  • 虽然 Android 的版本在不断地迭代,系统也变得越来越流畅,但是,国内用户的手机系统,由于各大手机厂商的定制化,基于的版本还是早几年的,更新换代没有跟上;
  • Android 手机存在着严重的碎片化和兼容性问题。开发的应用需要适配不同版本的系统和手机,同时,由于 Android 系统源码的开放性,国内手机厂商基于 Android 原生源码,改造成自己对外发布的系统,如小米手机的 MIUI 系统等。

因此,我们侧重在业务功能、交互符合逻辑和优化性能上着手,以筑成让用户满意的应用。

性能指标

或多或少存在着这样那样的问题,我们侧重在启动速度、流畅度、内存和功耗这四个点上进行优化。

I.启动速度

通常,我们点击一个应用图标,偶尔会先出现个白屏,然后才进入主界面。更有甚者,会出现黑屏的现象。

原因大抵是复杂的布局、UI 阻塞、过度绘制和初始化过程中执行了过多的操作。

可以配合 Hierarchy Viewer、StrictMode、TraceView 和 Hugo 来检测。

II.流畅度

前文提到,使用应用的过程中,某些地方会出现卡顿的情况,不是十分的顺畅。

原因会是上文提到的 UI 阻塞、过度绘制,还有是内存抖动和手机剩余不足的内存。

同样可以配合 StrictMode、TraceView 和 Hugo,还有 Android Studio 和手机的开发者选项。

说明下内存抖动即短时间内大量的对象被创建,然后又马上被释放,瞬间产生的大量对象,会严重占用年轻代的内存区域。一旦达到阈值,剩余空间不够的时候,会触发 GC,导致刚产生的对象很快被回收。如此,就算每次分配的对象很少,其叠加在一块会增加堆空间的压力,触发更多其他类型的 GC,以释放更多的可用内存。但是,GC 工作起来后,会吃掉帧时间(16ms),最终导致性能问题。

III.内存

不仅仅应用卡顿,整个手机操作过程中,又卡又慢。

原因会是说到的内存抖动,还有占用过多的内存,甚至还有导致的内存泄漏。

配合 Android Studio 和 LeakCanary 库侦测。

说明下内存泄漏即不正确的引用,导致某个对象无法被 GC 释放掉,从而可用的内存越来越少,导致频繁触发 GC 回收内存,进而造成性能的下降。

IV.功耗

手机在使用过程中发烫,出现掉电快的情况。

原因有硬件方面的,也有软件方面的,比如手机长时间未待机、后台在持续地工作、硬件自身持续地高负载工作、频繁的网络访问和频繁的刷新界面等。

这里,配合手机的开发者选项和 Android Studio 来侦测。

优化方案

I.优化启动速度

应用的启动主要完成 UI 布局、绘制界面和准备一些数据,那么可以监控启动速度,找出问题的所在。

UI 布局:应用启动时,一般会有闪屏页,可以配合手机开发者模式下的 Profile GPU Rendering 检测丢帧情况,以优化布局;

绘制界面:采用分步加载、异步加载和延期加载策略,提高应用启动的速度,配合 Hugo 大致定位耗时位置。

数据准备:采用线程初始化策略加载数据。

优化布局

布局合理与否影响着页面的测量时间,其中,一个页面的测量和绘制过程通过递归来完成,多叉树的遍历时间与树的高度 h 相关,时间复杂度为 O(h)。若层级太深,会增加不必要的页面显示时间。配合使用 Hierarchy Viewer,大概注意以下几点:

  • 减少层级:合理使用 RelativeLayout 和 LinearLayout,一般来说,单独的布局性能:
1
FrameLayout > LinearLayout > RelativeLayout

还有合理使用 merge 标签;

  • 减少不必要的 View 占位:使用 ViewStub,其是一个不占布局位置、耗用资源少、看不见的视图对象;
  • 提高复用率:使用 include 标签复用布局;
  • 少用 wrap_content,其会增加布局测量时的计算成本,同时,删除不用的属性。

切勿过度绘制

过度绘制,即屏幕上的某个像素在同一帧的时间内被绘制了多次。若不可见的 UI 也在做绘制的操作,则会浪费多余的 CPU 和 GPU 资源。配合使用手机的开发者选项,大概注意以下几点:

  • 优化布局:移除 XML 中非必需的背景,移除 Window 默认的背景,根据需要显示占位的背景图片;
  • 优化自定义 View:调用 canvas.clipRect() 帮助系统识别可见的区域。

此外,使用 AsyncTask、HandlerThread、IntentService 和 ThreadPool 的过程中,尽可能避免一切的 UI 阻塞。

II.优化流畅度

除了以上优化启动速度提到的点,配合使用 TraceView 和 Systrace 等,大概如下:

  • 在频繁调用的方法内,减少局部变量的申请;
  • 优化不必要的内存泄漏。

常见的内存泄漏场景如下:

  • 静态 Activity:在 Activity 类中定义了一个 static 变量,将其指向一个运行中的 Activity 实例,若在 Activity 的生命周期结束之前未清理该引用,就会造成内存泄漏。这是由于 Activity 的类对象是静态的,一旦加载,就会在 App 运行时常驻内存,故而,类对象不卸载,静态成员则不会被 GC;
  • 静态 View:一旦 View 被加入到界面中,就会持有 Context 的强引用,即我们的 Activity。若通过一个静态成员引用该 View,则同时引用了 Activity,故 Activity 发生内存泄漏。注意,不要把加载的 View 赋值给静态变量,就算需要,也要确保在 Activity 销毁之前将其从 View 层级中移除;
  • 内部类:往往为了增加代码的封装性和可读性,我们会在 Activity 内部定义一个类,即内部类。内部类通过持有外部类的引用来达到引用外部类的成员,若创建了一个内部类的对象,然后,通过静态变量持有了 Activity 的引用,也会发生内存泄漏;
  • 匿名类:匿名类也会持有定义其对象的引用,多线程编程时,若在 Activity 内定义了一个匿名的 AsyncTask 对象,在 Activity 被销毁之后 AsyncTask 仍然在执行,组织垃圾回收器无法回收该 Activity 对象,便导致内存泄漏;
  • Handlers:定义一个匿名的 Runnable 对象,该对象间接地引用定义它的 Activity 对象,其会被提交到 Handler 的 MessageQueue 中,若在 Activity 销毁时还未被处理,则会导致内存泄漏;
  • 资源性对象:Cursor、File 文件等,往往使用了一些缓冲,不使用时,未及时关闭也会引起内存泄漏;
  • 注册对象:事件、广播等,注册后未注销,造成观察者列表中维持着对象的引用,也会导致内存泄漏;
  • WebView:应用中只要使用一次 WebView,内存不会被释放掉,引起内存泄漏。

III.优化内存

移动设备上,由于物理设备的存储空间有限,Android 系统为每个应用进程分配了有限的堆内存,故使用最小的内存对象或资源,可以减小内存开销,同时,GC 能更高效地回收不再使用的对象。这样,堆内存保持充足的可用内存,进而应用可以稳定高效地运行。

除了优化流畅度提到的点,配合使用 Android Studio 自带的选项和 LeakCanary,大概如下:

  • 对象引用:强引用、软引用、弱引用和虚引用四种引用类型,由给定的业务需求合理使用不同的引用类型;
  • 内存开销:注意自动装箱机制,增加内存的复用,如有效地利用系统自带的资源,复用视图,使用对象池和复用 Bitmap 对象;
  • 数据类型:尽量避免使用枚举类型,可以使用缓存 LruCache,还有,针对数据类的容器结构,使用 ArrayMap;
  • 图片优化:由采样因子做压缩,可以设置位图规格,用一些图片缓存方式管理图片。

IV.优化功耗

配合使用 Android Studio 和开发者选项,大概如下:

  • 网络访问:合并网络请求,改善网络请求策略;
  • 界面刷新:改为触发时响应,不要在一进界面时就持续地刷新界面;
  • 待机:合理地使用 WakeLock;
  • 后台工作:优化系统后台工作。

至此,关于 Android 性能优化的概要介绍到此结束,后续会有专题的深入展开研究。

本人才疏学浅,如有疏漏错误之处,望读者中有识之士不吝赐教,谢谢。

1
Email: [email protected] / WeChat: Wolverine623

您也可以关注我个人的微信公众号码农六哥第一时间获得博客的更新通知,或后台留言与我交流

参考文献

1.http://t.cn/RHo7clO

2.https://mp.weixin.qq.com/s/ePEPNCcMPd2MlXkf1H6_7g

更多内容

深入 Android 性能优化二:谈谈 systrace