java的一个非常重要的优点是垃圾的回收,不再使用的对象内存会被垃圾回收器释放,当然还是有可能出现内存泄漏,
垃圾回收器会帮你管理内存,它做的不仅仅是释放不用的内存。
只有当某个对象不再被引用的时候,它的内存才会被回收,当被释放的对象引用扔然需要的时候就回出现内存泄漏,
比如在横竖屏切换时当前的activity会被销毁,数据将会全部丢失。解决的方法也很简单,
在清单文件的activity中添加 android:configChanges="orientation|keyboardHidden"或者复写 onConfigurationChanged()用于实现不同屏幕状态下的处理方式。
Android2.3中定义了strictMode类,它对检查内存泄漏有很大的帮助。在3.0以后的版本可以检查出:
Activity泄漏,其他对象泄漏,对象没有关闭造成的泄漏。
当然在应用中使用StrictMode类不仅仅用来检查内存泄漏,磁盘的读写耗时,网络操作的耗时,自定义速度的耗时
**此功能仅仅在开发和测试时开启,应用发布时要禁用。**
// 磁盘的读写速度
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // .detectAll()
.penaltyLog()
.build());
// SQLite 检测
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
// 检测那些代码执行的缓慢
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectCustomSlowCalls() // noteSlowCall() 有可能造成的缓慢代码
.penaltyDeath()
.build());
// 检测网络交互耗时
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectNetwork()
.penaltyDeath()
.build());
在这个特殊的实例中,StrictMode检测到一个违反,仅仅记录下这个问题信息。
垃圾回收可能会在不定的时间触发,你基本上没有办法来控制它出现的时机,有时你可以通过system.gc()
来提醒一下Android,但最终的回收时间还是要看虚拟机的心情。
以下情况会触发垃圾回收:
GC_FOR_MALLOC: 当堆被占满不能进行内存分配时,在分配新的对象前,部分没有被引用的对象会被回收掉。
GC_CONCURRENT: 当部分垃圾可供回收时,通常有很多对象可以回收。
GC_EXPLICIT: 显示调用System.gc()产生的垃圾回收。
GC_EXTERNAL_ALLOE: Android 3.0 Honeycomb 及以上版本不会出现(一切都在堆中被分配)。
GC_HPROF_DUMP_HEAP: 发生在创建HPROF文件时(HPROF实际上是JVM中的一个native的库)。
垃圾回收要花费时间,减少分配/释放对象的数量可以提高性能。在Android 2.2 之前垃圾回收在主线程中执行的,
所以严重的了降低了应用的速度和效率。在Android 2.3以后将垃圾回收移到了一个单独的线程中,但是在垃圾回收时还是会对主线程造成一定的影响。
Android 中定义了几个API,我们可以用他们来了解内存的使用所占的资源。
ActivityManager 的 getMemoryInfo() 系统可用内存信息。
ActivityManager 的 getMemoryClass() 获取堆内存的信息。
ActivityManager 的 getLargeMemoryClass() 获取最大的堆内存。
Debug 的 dumpHprofData() 将进程的内存写入到指定地址中。
Debug 的 getMemoryInfo() 检索各种统计有关该进程的内存映射。
ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
// 这里使用 memoryInfo 带来的数据
manager.getMemoryInfo(memoryInfo);
Debug.MemoryInfo debugMemory = new Debug.MemoryInfo();
// 这里使用 debugMemory的数据
Debug.getMemoryInfo(debugMemory);
你的应用不能独占平台,他要与许多其他的应用共享资源。因此当内存不足以分配给所有程序时,Android会要求应用及应用的组件节省资源。
如使用Fragment 中的replace在每一次切换的时候将上一个Fragment收回。
使用ComponentCallbacks接口定义 onLowMemory(),它对所有的应用组件都是相同的。
当他被调用时,组件基本会被要求释放那些并不会被用到的内存。
通常情况下onLowMemory()将释放:
缓存或缓存的条目
可以再次按照需求生成位图对象
不可见的布局对象
数据库对象
删除对象的时候要注意,因为重新创建是要消耗内存的,如果没有释放足够的内存可能会导致应用程序的进程被干掉。
在代码中推迟初始化是一个好习惯,它可以让你在实现onLowMemory()时几乎不用改动其他地方的代码。