安卓大军浩浩荡荡,发展已近十个年头,技术优化月新日异,如今 Android 9.0 代号P  都发布了,Android系统性能已经非常流畅了。但是,到了各大厂商手里,改源码自定系统,使得Android原生系统变得鱼龙混杂。另外,到了不同层次的开发工程师手里,因为技术水平的参差不齐,即使很多手机在跑分软件性能非常高,打开应用依然存在卡顿现象。另外,随着产品内容迭代,功能越来越复杂,UI页面也越来越丰富,也成为流畅运行的一种阻碍。综上所述,对APP进行性能优化已成为开发者该有的一种综合素质,也是开发者能够完成高质量应用程序的重要考核之一。

一、性能检测工具


(一)网易开源的Emmagee , https://github.com/NetEase/Emmagee   

    Emmagee(机关枪)是网易杭州研究院QA团队开发的一个简单易上手的Android性能监测小工具,主要用于监控单个App的CPU,内存,流量,启动耗时,电量,电流等性能状态的变化,且用户可自定义配置监控的频率以及性能的实时显示,并最终生成一份性能统计文件。对于手游实时分析CPU和内存占比帮助非常大。

(1)优势

  1. 开源;
  2. 无需root权限;
  3. 使用方便;
  4. 实时展示数据;
  5. CSV格式保存性能数据,方便转换为其它格式;
  6. 自定义采集频率;
  7. 支持2.2以及以上版本。(由于Google 安全限制,在7.0版本手机不支持,找个低版本手机去测就完了)

(2)检测案例

1、在GitHub下载安装包Apk

2、运行Emmagee.app。可以设置采集频率。

      

3、点击APP"测试报告"查看,也可以配置邮件下发CSV文件。而我选择盗取文件到电脑上用Excel表格看。

(本地内部存储Emmagee目录”storage\sdcard0\Emmagee\某日期时间_APP包名.csv”的文件,即为监控数据

操作adb查看命令:

[objc]  view plain  copy
  1. $ adb shell    //回车  
  2. $ cd storage/sdcard0/Emmagee/    //回车  
  3. $ ls   //回车 ,结果如下:  
  4.   
  5. 20180605154517_com.daojia.csv  
  6. 20180605160747_me.ele.csv  

*手机导出的csv文件出现乱码,原因是由于导出的CSV文件编码为UTF-8 。解决办法:(Windows)使用记事本打开另存为“ANSI编码”的CSV格式文件即可。(Mac OS)文本编辑打开重新保存即可。

上面分别是对到家点餐APP、饿了么点餐APP的CSV检测数据。移动文件到电脑Excel打开查看:




(二)腾讯开源的GT,https://github.com/TencentOpen/GT


(1)什么是GT?

    GT(随身调)安卓/IOS手机端调测组件,用于APP的性能测试、竞品测试及仅凭一台手机即可进行App测试。 利用GT,仅凭一部手机,无需连接电脑,您即可对APP进行快速的性能测试(CPU、内存、流量、电量、帧率/流畅度等)、 开发日志的查看、Crash日志查看、网络数据包的抓取、APP内部参数的调试、真机代码耗时统计等等;更重要的是,您可以在任意真实场所、 任何时候做如上的系列事情,这就是“APP的场测”。如果您觉得GT提供的功能还不够满足您的需要, 您还可以利用GT提供的基础API自行开发有特殊功能的GT插件(目前,仅iOS版支持), 帮助您解决更加复杂的APP调试、测试问题。

(2)如何使用?

    GT支持iOS和Android两个手机平台,其中: Android版由一个可直接安装的GT控制台APP 和GT SDK插件扩展检测。GT控制台可以独立安装使用,SDK需嵌入被调测的应用、并利用GT控制台进行信息展示和参数修改。 iOS版是一个Framework包,必须嵌入APP工程,编译出带GT的APP才能使用;iPhone和iPad应用都能支持。

此处以Android版GT控制台APP 检测主功能为案例,简要介绍使用步骤:

1、应用宝下载GT.APP,安装运行GT。

2、选择应用                                                                         

                

3、选择关注的监控数据                          4、结果展示

                                                   

(三)科大讯飞的iTest,http://www.liqucn.com/rj/410791.shtml

iTest官方介绍:

该工具由科大讯飞测试技术部开发,在多个项目中成功应用,具有较高的准确性和稳定性。它填补了手机端自动化测试的空白,以实用高效为宗旨,记录特定应用的性能消耗情况,包括cpu、内存、流量、电量等信息。效果图如下所示。


遗憾本人寻遍全网,只能查找下载安装Apk的地址,查阅其他的相关介绍和资料太少。

毕竟科大讯飞在业界是很有名气的是讯飞语音。

 

(四)Google的开源Battery Historian,https://github.com/google/battery-historian

文档是纯英文版的,使用需要配置环境,包括go/java/python/git的安装与配置。 从github上下载Battery Historian。经过一顿操作后,最终效果图如下。


由于需要花费大量时间和精力成本投入到研究当中,所以后期有机会再补全使用教程。


二、性能优化方法


    使用性能检查工具,可以将自身产品与竞争者产品做对比,发现自身的优势的同时,也可以找到自身产品存在的不足之处。那么,接下来需要思考自身产品如何进行性能的优化和改进的方法。本着人道主义,一切从用户体验的角度去思考,置身处地得把自己当做用户去玩一款应用时候会在意些什么呢?假如饭点将至,需要打开到家APP进行点餐,首先一定不希望,在浏览商家和菜品列表内容很丰富的时候遇到卡顿现象,然后千挑万选后在期待美食将至的心情下准备下单,突然遇到闪退崩溃那简直想卸载到家APP的心都有了。其次就是配送员在配送过程中不希望耗电和耗流量太严重。最后就是版本更新的时候安装包希望能小一点。     用户希望的四个方面需求总结如下:
  1. 稳定(内存溢出、崩溃)
  2. 流畅(卡顿)
  3. 耗损(耗电、流量)
  4. 安装包(APK瘦身)

(一)稳定——内存优化


     由于Android应用的沙箱机制,即每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例,系统默认给每个应用所分配的内存大小是有限度的,例如:华为mate7,192m ;小米4,128m ;红米,128m ;三星SM-N7508v:96m。Android4.0以后,可以通过在application节点中设置属性android:largeHeap=”true”来设置最大可分配多少内存空间就可以突破一定限制。但是,当系统内存太低依然会触发LMK(Low Memory Killer)机制,即闪退、崩溃现象。
以下分享本人总结Java内存分配及Android常见内存泄漏分析相关文章: Java 垃圾回收器的GC机制,看这一篇就够了  Android 内存泄漏常见案例及分析  
了解内存如何分配和回收机制的同学,对内存优化会有一定的认识和掌握。可以借助 内存分析工具,方便定位内存优化的代码。
举个例子,代码如下所示: [java]  view plain  copy
  1. public class CommUtil {  
  2.     private static CommUtil instance;  
  3.     private Context context;  
  4.     private CommUtil(Context context) {  
  5.         this.context=context;  
  6.     }  
  7.     public static CommUtil getInstance(Context context){  
  8.         if(null==instance){  
  9.             instance=new CommUtil(context);  
  10.         }  
  11.         return instance;  
  12.     }  
  13. }  
  14. public class MainActivity extends AppCompatActivity {  
  15.     @Override  
  16.     protected void onCreate(Bundle savedInstanceState) {  
  17.         super.onCreate(savedInstanceState);  
  18.         setContentView(R.layout.activity_main);  
  19.         CommUtil instance = CommUtil.getInstance(this);//  
  20.     }  
  21. }  
    一个工具类 CommUtil.class 使用创建型设计模式——单例模式,在MainActivity.class中引用,那么这个单例对象会持有Activity的实例。然后运行起来 ,再将手机屏幕旋转几下。这样的代码会造成什么错误?
(旋转屏幕的时候 Activity会被销毁重新创建,但是这里的单例会持有销毁Activity的实例就造成内存泄漏)

使用分析工具如下:

  • Memory Monitor 工具:
    它是Android Studio自带的一个内存监视工具,它可以很好地帮助我们进行内存实时分析。通过点击Android Studio右下角的Memory Monitor标签,打开工具可以看见较浅蓝色代表free的内存,而深色的部分代表使用的内存从内存变换的走势图变换,可以判断关于内存的使用状态,例如当内存持续增高时,可能发生内存泄漏;当内存突然减少时,可能发生GC等,如下图所示。 *案例参考

  • Memory Analyzer 工具:

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

(1)(屏幕多次翻转,出现内存持续增高时)点击 Dump java Heap就会生成运行内存快照hprof文件。


(2)然后将APP完全退出,重新启动,打开Android Monitor 再次点击Dump java Heap 生成一份还没操作(旋转屏幕)前的内存快照hprof文件。现在就已经生成好了2份hprof文件, 一份是没有旋转过屏幕的 ,一份是旋转过屏幕多次的。


(3)然后选中Android Studio 最左边的Captures 进行将hprof文件导出。导出的时候需要选择保存的目录以及文件名。



(4)打开MAT ,导入我们的2个hprof文件 Open File-->选择文件-->Leak Suspects Report-->Finish:*案例参考



  • LeakCanary工具:
    简单,傻瓜式操作。可以在GitHup官网查阅https://github.com/square/leakcanary我们可以在Gradle文件里添加依赖。这个工具是Square公司在Github开源的。行业内不是有一句话嘛,Square出品必属精品,主流的库像okhttp、Picasso、retrofit、Dagger等都出自Square之手。说到这不得不让我联想到一位在Android开发领域神一般存在的人物,他就是大名鼎鼎的Jake Wharton(杰克.沃顿),ButterKnife的创造者,也参与贡献了Retrofit, okhttp等。

  • Android Lint 工具:
    Android Lint Tool 是Android Sutido种集成的一个Android代码提示工具,它可以给你布局、代码提供非常强大的帮助。 硬编码会提示以级别警告,例如:在布局文件中写了三层冗余的LinearLayout布局、直接在TextView中写要显示的文字、字体大小使用dp而不是sp为单位,就会在编辑器右边看到提示。使用Android Studio的lint可以清除无用的资源文件:点击菜单栏的Analyze -> Run Inspection by Name, 输入unused resource。     当然以上都是一个简单的举例,Lint的功能非常强大,大家应该养成写完代码查看Lint的习惯,这不仅让你及时发现代码种隐藏的一些问题,更能让你养成良好的代码风格,要知道,这些Lint提示可都是Google大牛们汗水合智慧的结晶。

小结

    影响稳定性的原因很多,比如内存使用不合理、代码异常场景考虑不周全、代码逻辑不合理等,都会对应用的稳定性造成影响。其中最常见的两个场景是:Crash 和 ANR,这两个错误将会使得程序无法使用。所以做好Crash监控,把崩溃信息、异常信息收集记录起来,以便后续分析;合理使用主线程处理业务,不要在主线程中做耗时操作,防止ANR程序无响应发生。

二、流畅——交互优化

交互是与用户体验最直接的方面,交互场景大概分为四个部分:UI 绘制、应用启动、页面跳转、事件响应,如图:

四个方面大致归为如下两类:

  • 界面绘制主要原因是绘制的层级深、页面复杂、刷新不合理,由于这些原因导致卡顿的场景更多出现在 UI 和启动后的初始界面以及跳转到页面的绘制上。

  • 数据处理导致这种卡顿场景的原因是数据处理量太大,一般分为三种情况,一是数据在处理 UI 线程,二是数据处理占用 CPU 高,导致主线程拿不到时间片,三是内存增加导致 GC 频繁,从而引起卡顿。

分析:

    我们知道Android的绘制步骤是::Measure、Layout、Draw,所以布局的层级越深、元素越多、耗时也就越长。还有就是Android 系统每隔 16ms 发出 VSYNC 信号,触发对 UI 进行渲染,如果每次渲染都成功,这样就能够达到流畅的画面所需的 60FPS。如果某个操作花费的时间是 24ms ,系统在得到 VSYNC 信号时就无法正常进行正常渲染,这样就发生了丢帧现象。那么用户在 32ms 内看到的会是同一帧画面,无法在 16ms 完成渲染,最终引起刷新不及时。

两个根本原因:

  1. 绘制任务太重,绘制一帧内容耗时太长。

  2. 主线程太忙,根据系统传递过来的 VSYNC 信号来时还没准备好数据导致丢帧。


建议1:布局优化


    在Android种系统对View进行测量、布局和绘制时,都是通过对View数的遍历来进行操作的。如果一个View数的高度太高就会严重影响测量、布局和绘制的速度。Google也在其API文档中建议View高度不宜哦过10层。现在版本种Google使用RelativeLayout替代LineraLayout作为默认根布局,目的就是降低LineraLayout嵌套产生布局树的高度,从而提高UI渲染的效率。
  • 布局复用,使用标签重用layout;
  • 提高显示速度,使用延迟View加载;
  • 减少层级,使用标签替换父级布局;
  • 注意使用wrap_content,会增加measure计算成本;

  • 删除控件中无用属性


建议2:绘制优化

    过度绘制是指在屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的 UI 结构中,如果不可见的 UI 也在做绘制的操作,就会导致某些像素区域被绘制了多次,从而浪费了多余的 CPU 以及 GPU 资源。所以避免过度绘制:
  • 布局上的优化。移除 XML 中非必须的背景,移除 Window 默认的背景、按需显示占位背景图片

  • 自定义View优化。使用 canvas.clipRect()来帮助系统识别那些可见的区域,只有在这个区域内才会被绘制。


建议3:启动优化

  • UI 布局。应用一般都有闪屏页,优化闪屏页的 UI 布局,可以通过 Profile GPU Rendering 检测丢帧情况。
  • 启动加载逻辑优化。可以采用分布加载、异步加载、延期加载策略来提高应用启动速度。
  • 数据准备。数据初始化分析,加载数据可以考虑用线程初始化等策略。

建议4:刷新优化

  • 减少刷新次数;
  • 缩小刷新区域;

建议5:动画优化

  • 在实现动画效果时,需要根据不同场景选择合适的动画框架来实现。有些情况下,可以用硬件加速方式来提供流畅度。


三、节省——耗电优化


    在移动设备中,电池的重要性不言而喻,没有电什么都干不成。对于操作系统和设备开发商来说,耗电优化一致没有停止,去追求更长的待机时间,而对于一款应用来说,并不是可以忽略电量使用问题,特别是那些被归为“电池杀手”的应用,最终的结果是被卸载。因此,应用开发者在实现需求的同时,需要尽量减少电量的消耗。


    在 Android5.0 以前,在应用中测试电量消耗比较麻烦,也不准确,5.0 之后专门引入了一个获取设备上电量消耗信息的 API:Battery Historian。Battery Historian 是一款由 Google 提供的 Android 系统电量分析工具,和Systrace 一样,是一款图形化数据分析工具,直观地展示出手机的电量消耗过程,通过输入电量分析文件,显示消耗情况,最后提供一些可供参考电量优化的方法。


除此之外,还有一些常用方案可提供:

  • 计算优化,避开浮点运算等。

  • 避免 WaleLock 使用不当。

  • 使用 Job Scheduler。



四、APK瘦身


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

常用应用安装包的构成,如图所示:




从图中我们可以看到:

  • assets文件夹。存放一些配置文件、资源文件,assets不会自动生成对应的 ID,而是通过 AssetManager 类的接口获取。

  • res。res 是 resource 的缩写,这个目录存放资源文件,会自动生成对应的 ID 并映射到 .R 文件中,访问直接使用资源 ID。

  • META-INF。保存应用的签名信息,签名信息可以验证 APK 文件的完整性。

  • AndroidManifest.xml。这个文件用来描述 Android 应用的配置信息,一些组件的注册信息、可使用权限等。

  • classes.dex。Dalvik 字节码程序,让 Dalvik 虚拟机可执行,一般情况下,Android 应用在打包时通过 Android SDK 中的 dx 工具将 Java 字节码转换为 Dalvik 字节码。

  • resources.arsc。记录着资源文件和资源 ID 之间的映射关系,用来根据资源 ID 寻找资源。


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

  1. 代码混淆。使用proGuard 代码混淆器工具,它包括压缩、优化、混淆等功能。
  2. 资源优化。比如使用 Android Lint 删除冗余资源,资源文件最少化等。
  3. 图片优化。比如利用 PNG优化工具 对图片做压缩处理。推荐:zopfliPNG
  4. 避免重复功能的库,如果应用在4.0版本以上,使用 WebP图片格式等。
  5. 插件化。比如功能模块放在服务器上,按需下载,可以减少安装包大小。
  6. 可以使用微信开源资源文件混淆工具——AndResGuard 。一般可以压缩apk的1M左右大。


五、

    最后说一句,性能优化是一个非常具有挑战性的工作,上面列出很多分析内存、优化内存的方法,但是真正优化工作远不止这么简单,这里只是列举了一些入门的方法,而要进行完美的内存优化、内存分析绝非一日之功,需要开发者深厚的技术功底合耐心。

更多相关文章

  1. Android(安卓)SDK开发嵌套aar文件
  2. 刷中兴N760经历,最靠谱的方式刷Android有感
  3. 【构建Android缓存模块】(二)Memory Cache & File Cache
  4. android增加swap分区能提速反应很显著哦!
  5. android保存数据的四种方法
  6. Android(安卓)4.0 CTS Debug
  7. Android(安卓)MediaCodec 音频转码——硬编硬解
  8. Android7.1.2源码解析系列】Android编译系统翻译------Android_B
  9. Android(安卓)app中加载jar插件

随机推荐

  1. Android(安卓)联系人按中文拼音排序
  2. Android标题栏各种设置
  3. Android FrameLayout的显示效果
  4. Dagger2在Android studio中的配置与简单
  5. android 一些小功能实现
  6. 跑马灯效果
  7. 编译cubieboard android 源码过程详解之(
  8. android 模拟器常用命令
  9. Android实现启动页停留几秒然后自动跳转
  10. android 硬解码 是否支持