Android中UI检测、内存泄露、OOM、等优化处理

对Android整个优化分析,非常棒,下面是自己的积累笔记。可直接看原文。

[转] Android应用开发性能优化完全分析

界面检测工具:

  1. Fps: GPU检测,

  2. 使用Lint进行资源及冗余UI布局等优化 (很强大,布局的冗余)

  3. Memory检测GC打印(发现问题),Allocation Tracker(定位问题 通过这个工具我们可以很方便的知道代码分配了哪类对象、在哪个线程、哪个类、哪个文件的哪一行。) 进行UI卡顿分析。
    常见应用开发中导致GC频繁执行的原因主要可能是因为短时间内有大量频繁的对象创建与释放操作,也就是俗称的内存抖动现象,或者短时间内已经存在大量内存暂用介于阈值边缘,接着每当有新对象创建时都会导致超越阈值触发GC操作。

  4. Traceview 应用程序中每个函数的执行时间

  5. Systrace整个系统进行分析

  6. 使用traces.txt文件进行ANR分析优化.(发生Anr后adb pull /data/anr/traces.txt 输出 )
    代码UI性能:
    1.布局优化;尽量使用include、merge、ViewStub标签,尽量使用GONE替换INVISIBLE,使用weight后尽量将width和heigh设置为0dp减少运算,Item存在非常复杂的嵌套时考虑使用自定义Item View来取代,减少measure与layout次数等。
    2.列表及Adapter优化;尽量复用getView方法中的相关View,不重复获取实例导致卡顿,列表尽量在滑动过程中不进行UI元素刷新等
    3.背景和图片等内存分配优化;尽量减少不必要的背景设置,图片尽量压缩处理显示,尽量避免频繁内存抖动等问题出现。
    4.自定义View等绘图与布局优化;尽量避免在draw、measure、layout中做过于耗时及耗内存操作,尤其是draw方法中,尽量减少draw、measure、layout等执行次数。

内存性能优化分析

系统级内存管理:
1. Linux在进程停止后就结束该进程,而Android把这些停止的进程都保留在内存中,直到系统需要更多内存时才选择性的释放一些,保留在内存中的进程默认(不包含后台service与Thread等单独UI线程的进程)不会影响整体系统的性能(速度与电量等)且当再次启动这些保留在内存的进程时可以明显提高启动速度,不需要再去加载。
直白点就是说Android系统级内存管理机制其实类似于Java的垃圾回收机制
应用级内存管理:
1. 每个Android应用程序都执行在自己的虚拟机中,那了解Java的一定明白,每个虚拟机必定会有堆内存阈值限制(值得一提的是这个阈值一般都由厂商依据硬件配置及设备特性自己设定。
2. 运行的App在自己的虚拟机中内存管理基本就是遵循Java的内存管理机制了,系统在特定的情况下主动进行垃圾回收。但是要注意的一点就是在Android系统中执行垃圾回收(GC)操作时所有线程(包含UI线程)都必须暂停,等垃圾回收操作完成之后其他线程才能继续运行。这些GC垃圾回收一般都会有明显的log打印出回收类型,常见的如下:
LeakCanary:
dumpsys meminfo:
MAT Java堆内存泄露分析:

Android应用开发规避内存泄露建议

  1. Context使用不当造成内存泄露
  2. 非静态内部类的静态实例容易造成内存泄漏;即一个类中如果你不能够控制它其中内部类的生命周期(譬如Activity中的一些特殊Handler等),则尽量使用静态类和弱引用来处理
  3. 警惕线程未终止造成的内存泄露,譬如在Activity中关联了一个生命周期超过Activity的Thread,在退出Activity时切记结束线程。(比如说AsyncTask等)
  4. 譬如在Activity中关联了一个生命周期超过Activity的Thread,在退出Activity时切记结束线程
  5. 譬如在Activity中关联了一个生命周期超过Activity的Thread,在退出Activity时切记结束线程
  6. 不要在执行频率很高的方法或者循环中创建对象,可以使用HashTable等创建一组对象容器从容器中取那些对象,而不用每次new与释放。

Android 内存溢出

(img)
产生原因:
1.应用代码存在内存泄露,长时间积累无法释放导致OOM;
2.应用的某些逻辑操作疯狂的消耗掉大量内存(譬如加载一张不经过处理的超大超高清图片等)导致超过阈值OOM。

Android应用规避内存溢出OOM建议

  1. 不要加载过大对象
  2. 优化界面交互过程中频繁的内存使用;譬如在列表等操作中只加载可见区域的Bitmap、滑动时不加载、停止滑动后再开始加载。
  3. 有些地方避免使用强引用,替换为弱引用等操作。
  4. 避免各种内存泄露的存在导致OOM。
  5. 对批量加载等操作进行缓存设计,譬如列表图片显示,Adapter的convertView缓存等。
  6. 对于有缓存等存在的应用尽量实现onLowMemory()和onTrimMemory()方法。
  7. 对于有缓存等存在的应用尽量实现onLowMemory()和onTrimMemory()方法。
  8. 尽量管理好自己的Service、Thread等后台的生命周期,不要浪费内存占用。
  9. 尽量在做一些大内存分配等可疑内存操作时进行try catch操作,避免不必要的应用闪退
  10. 尽量的优化自己的代码,减少冗余,进行编译打包等优化对齐处理,避免类加载时浪费内存。

HashMap, SparseArray,ArrayMap

HashMap:
HashMap内部使用一个默认容量为16的数组来存储数据,数组中每一个元素存放一个链表的头结点,其实整个HashMap内部结构就是一个哈希表的拉链结构。HashMap默认实现的扩容是以2倍增加,且获取一个节点采用了遍历法,所以相对来说无论从内存消耗还是节点查找上都是十分昂贵的。
SparseArray:
SparseArray比HashMap省内存是因为它避免了对Key进行自动装箱(int转Integer),它内部是用两个数组来进行数据存储的(一个存Key,一个存Value),它内部对数据采用了压缩方式来表示稀疏数组数据,从而节约内存空间,而且其查找节点的实现采用了二分法,很明显可以看见性能的提升。
ArrayMap:
ArrayMap内部使用两个数组进行数据存储,一个记录Key的Hash值,一个记录Value值,它和SparseArray类似,也会在查找时对Key采用二分法。
有了上面的基本了解我们可以得出结论供开发时参考,当数据量不大(千位级内)且Key为int类型时使用SparseArray替换HashMap效率高;当数据量不大(千位级内)且数据类型为Map类型时使用ArrayMap替换HashMap效率高;其他情况下HashMap效率相对高于二者。

Android应用ContentProviderOperation优化建议

ContentProvider是Android应用开发的核心组件之一,有时候在开发中需要使用ContentProvider对多行数据进行操作,我们的做法一般是多次调运相关操作方法,殊不知这种实现方式是非常低性能的,取而代之的做法应该是使用批量操作,具体为了使批量更新、插入、删除数据操作更加方便官方提供了ContentProviderOperation工具类。所以在我们开发中遇到类似情景时请务必使用批量操作,具体的优势如下:
• 所有的操作都在一个事务中执行,可以保证数据的完整性。
• 批量操作在一个事务中执行,所以只用打开、关闭一个事务。
• 减轻应用程序与ContentProvider间的多次频繁交互,提升性能。
可以看见,这对于数据库操作来说是一个非常有用的优化措施,烦请务必重视(我们项目优化过,的确有很大提升)。

Android应用移动设备电池耗电性能分析

adb shell dumpsys batterystats

常见耗电量最大原因基本都是因为网络数据交互、GPS定位、大量内存性能问题、冗余的后台线程和Service等造成。

Android应用耗电量优化建议

  1. 先进行网络状态判断在执行。
  2. 对定位要求不太高的场景尽量使用网络定位,而不是GPS定位
  3. 对于定时任务尽量使用AlarmManager,而不是sleep或者Timer进行管理。

你可能感兴趣的:(Android中UI检测、内存泄露、OOM、等优化处理)