代码写久了,就得开始考虑性能及架构的事情了
内存优化:
Android采用沙箱机制,每个应用所分配的内存大小是有限的,内存太低就会触发LMK----->Low Memory Killer机制。
手机的RAM(内存),包含以下几个部分:
- 寄存器(Registers)
速度最快的存储场所,因为寄存器位于处理器内部,在程序中无法控制。 - 栈(Stack)
存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中。 - 堆(Heap)
堆内存用来存放由new创建的对象和数组。在堆中分配的内存,由Java虚拟机的自动垃圾回收器(GC)来管理。 - 静态存储区域(Static Field)
指在固定的位置存放应用程序运行时一直存在的数据,Java在内存中专门划分了一个静态存储区域来管理一些特殊的数据变量如静态的数据变量。 - 常量池(Constant Pool)
JVM虚拟机必须为每个被封装的类型维护一个常量池。
常量池就是该类型所用到的常量的一个有序集合,包括直接常量(基本类型、String)和对其它类型、字段和方法的符号引用。
在这些概念中最容易搞错的就是堆和栈的区分。
当定义一个变量,Java虚拟机就会在栈中为该变量分配内存空间,当该变量作用于结束后,这部分内存空间会马上被用作新的空间进行分配。
如果使用new的方式创建一个变量,那么就会在堆中为这个对象分配内存空间,即使该对象的作用于结束,这部分内存也不会立即被回收,而是等待系统GC进行回收。
堆的大小随着手机的不断发展而不断变大。
在程序中,可以使用如下代码来获得堆的大小,所谓的内存分析,正是分析Heap中的内存状态。
ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
int heapSize = manager.getLargeMemoryClass();
Log.d("heapSize", "-------->"+heapSize);
ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
int heapSize = manager.getLargeMemoryClass();
Log.d("heapSize", "-------->"+heapSize);
俺们手机的堆内存大小:heapSize: -------->256
获取Android系统内存信息
- Process Stats
可以通过"Setting-Developer options - Process Stats"(设置->开发者选项->进程统计信息)来开启该功能的界面,
同时,也可以使用Dumpsys命令来获取这些信息,命令如下:
adb shell sumpsys procstats - Meminfo
- 内存回收
Java有垃圾收集器线程(Garbage Collection Thread)来自动进行资源的管理。
大大降低了程序开发人员对内存管理的繁琐工作。
但也带来了很多问题,系统自动进行GC,但是何时进行却是开发者无法控制的,即使调用System.gc()方法,也只是建议系统进行GC,
但系统是否采纳你的建议,那就不一定了。
JVM虚拟机虽然能够自动控制GC,但是再强大的算法,也难免会存在部分对象忘记回收的现象发生,这就是造成内存泄露的原因。 - 内存优化实例
Bitmap优化
BitMap是造成内存占用过高甚至是OOM(Out of Memory)的最大威胁,下面给出一些使用Bitmap的小技巧
1、使用适当分辨率和大小的图片
由于Android系统在做资源适配的时候,会对不同分辨率文件夹下的图片进行缩放来适配相应的分辨率,如果图片分辨率与资源文件夹分辨率不匹配 或者 图片分辨率 太高,
就会导致系统消耗更多的内存资源。同时,在适当的时候,应该显示合适大小的图片,
例如在图片列表界面,可以使用图片的缩略图,而在详细图片的时候再显示原图;
或者在对图像要求不高的地方,尽量降低图片的精度。
2、及时回收内存
一旦使用完Bitmap后,一定要及时使用bitmap.recycle()方法释放内存资源。自Android3.0之后,由于Bitmap被放置到了堆中,其内存由GC管理,就不需要进行释放了。
3、使用图片缓存
通过内存缓存(LruCache)和硬盘缓存(DiskLruCache),可以更好地使用Bitmap.
代码优化:
任何Java类,都将占用大约500字节的内存空间。创建一个类的实例会消耗大约15字节的内存。从代码的实现上,也可以对内存进行优化:
1、对常量使用static修饰符
2、使用静态方法,静态方法比普通方法提高15%左右的访问速度
3、减少不必要的成员变量,这点在Android Lint工具上已经集成检测了,如果一个变量可以定义为局部变量,则会建议你不要定义为成员变量。
4、减少不必要的对象,使用基础类型会比使用对象更加节省资源,同时更应该避免频繁创建短作用域的变量
5、尽量不要使用枚举、少用迭代器
6、对Curcor、Receiver、Sensor、File等对象,要非常注意对它们的创建、回收和注册、解注册
7、避免使用IOC框架,IOC通常使用注解、反射来进行实现,虽然现在Java对反射的效率已经进行了很好的优化,但大量使用反射依然会带来性能的下降
8、使用RenderScript、OpenGL来进行非常复杂的绘图操作
9、使用SurfaceView来替代View进行大量、频繁的绘图操作
10、尽量使用视图缓存,而不是每次都执行inflate()方法解析视图
- AndroidLint工具
看代码编辑器右边的提示,哇塞,原来这么多,我得去琢磨修改下自己的代码了。。。 - 使用Android Studio的Memory Monitor工具
如图所示,我的监测,浅色代表free的内存,蓝色代表使用的内存从内存变换的走势图,可以判断关于内存的使用状态,
例如当内存持续增高时,可能发生内存泄露。
当内存突然减少时,可能发生了GC等。