1,如何检测内存问题
(1).检测工具:LeakCanary(效果直观,并且配置也比较简单)
在项目的build.gradle中加入引用
在application中初始化LeakCanary,到此处配置完成
发生内存泄漏提示
当前就从网络上获取到了一张关于,在发生内存泄漏的时候,会在通知栏出现一个提示图标,当点击进去之后,会直观的展示内存泄漏的位置。
注意:==通过LeakCanary的使用,它可以为我们快速找到内存泄漏的位置,但并不能够提供我们内存泄漏的原因,有的时候,内存泄漏的位置是由于其他原因导致的,
(2)检测工具:StrictMode
StrictMode的功能主要分为两大块:
一块是关于Thread,线程规范的监测,另一块是关于VM,内存的监测。在StrictMode下分别是ThreadPolicy和VMPloicy。
ThreadPolicy:用于监测线程部分,监测 主线程中是否访问网络、主线程中是否读写磁盘等。
VMPolicy:用于监测内存,可以监测Activity的内存泄漏,Fragment的内存泄漏(虽然内部没有指定Fragment可用的API但内部关于类对象的检测机制在此处就有着异曲同工之妙的作用),SQL内存泄漏,是否正常关闭读写流以及可以指定某个类的最大对象数目
2,内存溢出和泄漏的区别及常见内存问题
内存溢出是指当对象的内存占用已经超出分配内存的空间大小,这时未经处理的异常就会抛出。比如常见的内存溢出情况有:bitmap过大;引用没释放;资源对象没关闭
如图,这是常见的bitma对象的溢出,显示像素过高或图片尺寸远远大于显示空间的尺寸时,通常都要将其缩放,减小占用内存。
内存溢出的原因
(1)、内存泄露导致
由于我们程序的失误,长期保持某些资源(如Context)的引用,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造成内存泄露。
Android 中常见就是Activity被引用在调用finish之后却没有释放,第二次打开activity又重新创建,这样的内存泄露不断的发生,则会导致内存的溢出。
Android的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行,它是由Zygote服务进程孵化出来的,也就是说每个应用程序都是在属于自己的进程中运行的。Android为不同类型的进程分配了不同的内存使用上限,如果程序在运行过程中出现了内存泄漏的而造成应用进程使用的内存超过了这个上限,则会被系统视为内存泄漏,从而被kill掉,这使得仅仅自己的进程被kill掉,而不会影响其他进程.
(2)、占用内存较多的对象
保存了多个耗用内存过大的对象(如Bitmap)或加载单个超大的图片,造成内存超出限制。
3:内存泄漏(memory leak)
有些对象只有有限的生命周期。当它们的任务完成之后,它们将被垃圾回收。如果在对象的生命周期本该结束的时候,这个对象还被一系列的引用,这就会导致内存泄漏。随着泄漏的累积,app将消耗完内存。
比如,在Activity.onDestroy()被调用之后,view树以及相关的bitmap都应该被垃圾回收。如果一个正在运行的后台线程继续持有这个Activity的引用,那么相关的内存将不会被回收,这最终将导致OutOfMemoryError崩溃。
memory leak会最终会导致out of memory!
1.资源对象没关闭
如Cursor,File等资源。他们会在finalize中关闭,但这样效率太低。容易造成内存泄漏
SQLiteCurost,当数据量大的时候容易泄漏
2.使用Adapter时,没有使用系统缓存的converView
3.没有即时调用recycle()释放不再使用的bitmap
4.使用application的context来替代activity相关的context
不要让生命周期长于Activity的对象持有到Activity的引用
5.广播注册没取消造成内存泄露
6.Handler应该申明为静态对象, 并在其内部类中保存一个对外部类的弱引用。