Android学习十二周_Android性能优化

1.内存管理

1.垃圾回收机制
(1)什么是垃圾回收机制?

(a)垃圾回收器负责回收程序中已经不再使用,但是仍然被各种对象占用的内存。

(b)无需手动管理内存,Android系统会自动跟踪所有的对象,并释放那些不再被使用的对象。

缺点:垃圾回收机制是一把双刃剑,在提高程序员工作效率的同时,会对应用程序的性能造成影响,严重的会是应用程序卡顿等。
2.Android中的垃圾回收机制
这里写图片描述
(1)Young Generation

  • 大多数新建的对象都位于Eden区
  • 当Eden区被对象填满时,就会执行Minor GC。并把说有存活下来的对象转移到其中一个survivor区。
  • Survivor Space:S0、S1有两个,存放每次垃圾回收后存活的对象。
  • Minor GC同样检测Survivor区存活的对象,并把它们转移到另一个survivor中,这样的话总有一个空的survivor区。

(2)Old Generation

  • 存放长期存活的对象和经过多次Minor GC后依然存活下来的对象
  • 满了进行Major GC

(3)permanent Generation

  • 存放方法区,方法区中要加载的类的信息、静态变量、final类型的常量、属性和方法信息

3.垃圾回收

这里写图片描述
内存占用过多,需要为新对象分配空间,不同的虚拟机在发生GC时采用的策略不同,可能会暂停当前程序的执行。如上图,峰值后占用内存减少,是系统进行了一次垃圾回收。

4.垃圾回收机制&FPS

这里写图片描述

  • Android没间隔16ms发出VSYNC信号,触发对UI进行渲染,那么整个过程如果保证在16ms以内能达到一个流畅的画面。60FPS。
  • 如果某一帧的操作超过了16ms就会让用户感觉到卡顿。
  • UI渲染过程中发生GC,导致某一帧绘制超过16ms。

综上,系统在垃圾回收时可能会暂停当前程序的执行,这样有可能会导致某一帧的绘制超过了16ms,用户就会感觉卡顿。

5.内存泄漏

  • 应用程序分配了大量不能被回收的对象
  • 系统可分配内存越来越小
  • 新对象的创建需要的内存不足
  • GC之后再分配
  • 60FPS

综上,内存泄露指的是应用程序在运行时分配了一些的对象,这些对象所占用的内存并不能被垃圾回收程序所回收——导致系统可分配内存越来越少——新对象的创建需要的内存不够——调用垃圾回收程序执行一次垃圾回收——垃圾回收可能会暂停当前程序的执行——可能会导致某一帧的绘制超过16ms,影响到当前的帧率——帧率达不到60fps——用户感到卡顿。

6.内存检测工具

1.Memory Monitor
这里写图片描述
2.Allocation Tracker
这里写图片描述
这里写图片描述
主要用来追踪应用程序在运行时,所有已创建的对象、对象的数量、占用内存大小、以及这些对象是在哪些方法中被创建出来的信息。 点击图上2处,再次点击Allocation Tracker,AS会打开Allocation Tracker统计结果。

7.内存抖动

内存抖动是因为短时间内大量的对象被创建又马上被释放。瞬间产生大量的对象会严重占用Young Generation的内存区域,当达到阈值,剩余空间不够的时候,会触发GC从而导致刚产生的对象很多又被回收。即使每次分配的对象占用了很少的内存,但是它们叠加在一起回增加Heap的压力,从而触发更多其他类型的GC。这个过程可能会影响到帧率,并让用户感知到性能问题。
这里写图片描述

8.Heap Viewer

该工具可实时展示应用程序在运行时所有已分配对象的数量、大小、类型等信息。
这里写图片描述

上面三点的总结,对于Memory Monitor:
方便显示内存使用和GC情况;
快速定位卡顿是否和GC有关;
快速定位Crash是否和内存占用过高有关;
快速定位潜在的内存泄露问题;
缺点:不能准确定位问题,只能提供大概的方向。

对于Allocation Tracker :
定位代码中分配的对象的类型、大小、时间、线程、堆栈等信息;
定位内存抖动问题;
配合Heap Viewer一起定位内存泄露问题
缺点:使用复杂。

对于Heap Viewer:
内存快照信息
每次GC之后收集一次信息
查找内存泄露利器
缺点:使用复杂。

9.常见的内存泄露问题

1.单例造成的内存泄露

这里写图片描述
静态变量在整个程序的运行期间是一直存在的,不会被垃圾回收;静态变量本身会持有一个activity对象的引用的,activity对象即使被销毁了也不会被垃圾回收,从而造成了内存泄露。
2.非静态内部类的静态实例造成的泄露
这里写图片描述
TestResource是在MainActivity定义的非静态内部类,
其对象sResource对象会间接的持有MainActivity实例的引用,又把sResource定义为静态变量,所以在程序运行期间sResource对象不会被垃圾回收,并且一直持有MainActivity的引用,导致MainActivity也不会被垃圾回收。
3.Handler造成的内存泄露
这里写图片描述
创建一个匿名内部类的对象,它会间接持有外部类实例的引用;Handler经常用来做耗时的操作,可能存活时间比MainActivity实例时间长,所以可能会导致MainActivity销毁后并不能被垃圾回收,必须要等Handler被垃圾回收之后,MainActivity对象才会被垃圾回收。

避免内存泄露的方法:

a) 尽量不要让静态变量引用Activity;如果要用,尽量使用WeakReference;
b) 使用静态内部类来代替内部类(静态内部类不会持有它外部类的引用);
c) 静态内部类使用弱引用来引用外部类

10、减少内存的使用

  • 使用更轻量的数据结构
  • 避免在ondraw方法中创建对象
  • 对象池(Message.obtain())
  • LRUCache
  • bitmap内存复用,压缩(imSampleSize、inBitmap)
  • StringBuilder
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值