android 性能分析案例

本章以实际案例分析在android开发中,性能方面的优化和处理。设计到知识点有弱引用,memory monitor,Allocation Tracker和leakcanary插件。

1.测试demo

下载bug项目:https://github.com/lzyzsd/MemoryBugs,请注意配合使用MemoryMonitor, AllocationTracker以及HeapDump,LeakCanary等工具来查找潜在的内存问题,并尝试解决。

2.测试工具介绍

(1)memory monitor简介

AndroidStudio提供了Memory Monitor来实时显示应用运行时内存占用情况,下边蓝色部分是现在占用的内存,上面灰色的部分显示是已回收的内存。如果在图上看到尖峰,也就是快速分配内存又被回收,也就是发生了内存抖动,这里就是需要优化的地方。在模拟器或者真机中Debug项目,可实时监看Memory,CPU,NetWork等的资源占用情况。

(2)Allocation Tracker简介

单击Allocation tracker标签,就会打开一个新的窗口,单击“Start Tracing”按钮;然后,让应用运行你想分析的代码。运行完毕后,单击“Get Allocations”按钮,一个已分配对象的列表就会出现第一个表格中。

单击第一个表格中的任何一项,在表格二中就会出现导致该内存分配的栈跟踪信息。通过allocation tracker,不仅知道分配了哪类对象,还可以知道在哪个线程、哪个类、哪个文件的哪一行。查看方式如下:

  • Group by Method:用方法来分类我们的内存分配
  • Group by Allocator:用内存分配器来分类我们的内存分配

统计模式

轮胎图是以圆心为起点,最外层是其内存实际分配的对象,每一个同心圆可能被分割成多个部分,代表了其不同的子孙,每一个同心圆代表他的一个后代,每个分割的部分代表了某一带人有多人,双击某个同心圆中某个分割的部分,会变成以你点击的那一代为圆心再向外展开。如果想回到原始状态,双击圆心就可以了。

圆心是起点处,如果你把鼠标放到我图中标注的区域,会在右边显示当前指示的是什么线程(Thread1)以及具体信息(分配了8821次,分配了 564.18k的内存),但是红框标注的区域并不代表Thread1,而是第一个同心圆中占比最大的那个线程,所以现在把鼠标放到第一个同心圆上,可 以看出来,划过同心圆的轨迹时可以看到右边的树枝的变化情况。

3.案例分析

(1)内存波动

内存波动指不合理的设计,在一瞬间创建了多个对象,有及时释放时产生影响内存性能的现象。案例中的问题代码如下:

执行代码引起内存波动的分析图如下:

改良方案

不应该在for语句里面频繁的New对象。可先在外面创建好一个对象,在for里面直接调用对象。具体代码修改,请参考最后上传性能改良后的代码。改良后内存监控如同所示:

(2)线程致使内存泄露

Android中使用Handler造成内存泄露的例子代码如下:

1 Handler mHandler = new Handler() {
2     @Override
3     public void handleMessage(Message msg) {
4         mImageView.setImageBitmap(mBitmap);
5     }
6 }

泄露原因分析

上面是一段简单的Handler的使用。当使用内部类(包括匿名类)来创建 Handler的时候,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用(不然就不可能通过Handler来操作 Activity中的View)。而Handler通常会伴随着一个耗时的后台线程(例如从网络拉取图片)一起出现,这个后台线程在任务执行完毕(例如 图片下载完毕)之后,通过消息机制通知Handler,然后Handler把图片更新到界面。然而,如果用户在网络请求过程中关闭了Activity,正常情况下,Activity不再被使用,它就有可能在GC检查时被回收掉,但由于这时线程尚未执行完,而该线程持有Handler的引用,这个Handler又持有Activity的引用,就导致该Activity无法被回收(即内存泄露),直到网络请求结束(例如图片下载完毕)。另外,如果你执行了Handler的postDelayed()方法,该方法会将你的Handler装入一个Message,并把这条 Message推到MessageQueue中,那么在你设定的delay到达之前,会有一条MessageQueue -> Message -> Handler -> Activity的链,导致你的Activity被持有引用而无法被回收。

内存泄露的危害
    
内存泄露会出现虚拟机占用内存过高的危害,导致OOM(内存溢出),程序出错。对于Android应用来说,用户打开一个Activity,使用完之后关闭它,内存泄露;又打开,又关闭,又泄露;几次之后,程序占用内存超过系统限制,致使程序崩溃。使用Handler导致内存泄露的解决方法如下:

  • 通过程序逻辑来进行保护

1.在关闭Activity的时候停掉你的后台线程。线程停掉了,就相当于切断了Handler和外部连接的线,Activity自然会在合适的时候被回收。
    
2.如果Handler是被delay的Message持有了引用,使用相应的Handler的removeCallbacks()方法,把消息对象从消息队列移除就行了。

  • 将Handler声明为静态类

静态类不持有外部类的对象,所以Activity可以随意被回收。代码如下:

1 static class MyHandler extends Handler {
2     @Override
3     public void handleMessage(Message msg) {
4         mImageView.setImageBitmap(mBitmap);
5     }
6 }

声明静态类后,由于Handler不再持有外部类对象的引用,导致程序不允许该Handler去操作Activity中的对象了。解决方法是在Handler中增加一个对Activity的弱引用(WeakReference)。参考代码如下:

 1 static class MyHandler extends Handler {
 2     WeakReference<Activity > mActivityReference;
 3     MyHandler(Activity activity) {
 4         mActivityReference= new WeakReference<Activity>(activity);
 5     }
 6
 7     @Override
 8     public void handleMessage(Message msg) {
 9         final Activity activity = mActivityReference.get();
10         if (activity != null) {
11             mImageView.setImageBitmap(mBitmap);
12         }
13     }
14
15 }

WeakReference简介
    
WeakReference 弱引用,与强引用(即我们常说的引用)相对,它的特点是,GC在回收时会忽略掉弱引用,即就算有弱引用指向某对象,但只要该对象没有被强引用指向(实际上多数时候还要求没有软引用,但此处软引用的概念可以忽略),该对象就会在被GC检查到时回收掉。对于上面的代码,用户在关闭Activity之后,就算后台线程还没结束,但由于仅有一条来自Handler的弱引用指向Activity,所以GC仍然会在检查的时候把Activity回收掉。这样,内存泄露的问题就不避免了。

案例中存在hander内存泄露的代码截图如下:

通过上一章介绍的leakcanary插件,可检查到内存泄露相关的代码,leakcanary检查运行截图如下:

4.性能改良后源代码

本项目源代码在360云盘上,开发环境为 Android Studio 2.0 。

https://yunpan.cn/cPSA8uyeL2CwY  访问密码 dc98。文件名称:android性能改良代码。

时间: 2024-12-20 08:26:37

android 性能分析案例的相关文章

Android性能分析工具介绍

1. Android系统性能调优工具介绍 http://blog.csdn.net/innost/article/details/9008691 TraceviewSystraceOprofile 2. [腾讯开源]Android性能测试工具APT使用指南 http://www.csdn.net/article/2014-04-23/2819366-tencent-APT-open-source-tool-guide APT源码地址:https://code.csdn.net/Tencent/a

android 性能分析、优化

1.主要介绍了一些分析工具,比如GT.ITest等http://www.jianshu.com/p/8b77d394b2a6 2.详细介绍啦android平台常见性能优化工具http://blog.csdn.net/yanbober/article/details/48394201例如:UI方面:android系统提供的GPU OverDraw 过度绘制工具:GPU呈现模式分析等. Lint快速分析不合理懂UI布局:HierarchyViewer 具体分析View布局.内存方面:介绍了Memor

Android 性能分析工具之 TraceView 使用说明

TraceView 是 Android 平台配备一个很好的性能分析的工具.它可以通过图形化的方式让我们了解我们要跟踪的程序的性能,并且能具体到 method. TraceView 简介 TraceView 是 Android 平台特有的数据采集和分析工具,它主要用于分析 Android 中应用程序的 hotspot.TraceView 本身只是一个数据分析工具,而数据的采集则需要使用 Android SDK 中的 Debug 类或者利用 DDMS 工具.二者的用法如下: 开发者在一些关键代码段开

正确使用Android性能分析工具&mdash;&mdash;TraceView

前面唠叨 最近公司app中有些列表在滑动的时候会有卡顿现象,我就开始着手解决这些问题,解决问题之前首先要分析列表滑动的性能瓶颈在什么地方.因为之前不会正确使用TraceView这个工具,主要是看不懂TraceView界面下方数据指标的值代表什么意思-以前我用StopWatch类来分析性能,现在觉得弱爆了-不过有些地方StopWatch工具类还是很简单好用的~ 网上可以找了很多博客来介绍这个工具的使用方法,很多都是讲解了一些一些就会的方法,讲一个大概,包括StackOverFlow上我也没有找到很

mysql语句性能分析案例

写法不一样而功能完全相同的两条 SQL 的在性能方面的差异.示例一需求:取出某个 group(假设 id 为 100)下的用户编号(id),用户昵称(nick_name).用户性别( sexuality ) . 用 户 签 名 ( sign ) 和 用 户 生 日 ( birthday ) , 并 按 照 加 入 组 的 时 间(user_group.gmt_create)来进行倒序排列,取出前 20 个.解决方案一.SELECT id,nick_nameFROM user,user_group

Android 常用的性能分析工具详解:GPU呈现模式, TraceView, Systrace, HirearchyViewer(转)

此篇将重点介绍几种常用的Android性能分析工具: 一.Logcat 日志 选取Tag=ActivityManager,可以粗略地知道界面Displaying的时间消耗.当我们打开一个Activity的时候,log会打印一串log如下: I/ActivityManager﹕ Displayed xxx.xxx.xxx/TestActivity: +1s272ms (total +3s843ms) 第一个时间表示系统接受到打开的intent到TestActivity界面显示出来的时间1.272秒

Android APP性能分析方法及工具

近期读到<Speed up your app>一文.这是一篇关于Android APP性能分析.优化的文章.在这篇文章中,作者介绍他的APP分析优化规则.使用的工具和方法.我觉得值得大家借鉴.英文好的读者可读原文(链接:http://blog.udinic.com/2015/09/15/speed-up-your-app). 1.作者的规则 作者每次着手处理或寻找性能问题时,遵循下列规则: 时常检测 在更新APP前后,用测试工具软件多检测几次APP性能,可快速得到测试数据.这些数字是不会说谎的

Android 性能优化 五 性能分析工具dumpsys的使用

Android提供的dumpsys工具可以用于查看感兴趣的系统服务信息与状态,手机连接电脑后可以直接命令行执行adb shell dumpsys 查看所有支持的Service但是这样输出的太多,可以通过dumpsys | grep "DUMP OF SERVICE" 仅显示主要的Service的信息 一.列出dumpsys所有支持命令 > adb shell $ dumpsys | grep "DUMP OF SERVICE" 以下是在我个人三星S3手机上的输

Android绘制优化(一)绘制性能分析

前言 一个优秀的应用不仅仅是要有吸引人的功能和交互,同时在性能上也有很高的要求.运行Android系统的手机,虽然配置在不断的提升,但仍旧无法和PC相比,无法做到PC那样拥有超大的内存以及高性能的CPU,因此在开发Android应用程序时也不可能无限制的使用CPU和内存,如果对CPU和内存使用不当也会造成应用的卡顿和内存溢出等问题.因此,应用的性能优化对于开发人员有着更高的要求.Android性能优化分为很多种,比较常用的有绘制优化.内存优化.耗电优化和稳定性优化等,这个系列我们就来学习性能优化