0.
其实很多时候的内存泄漏都是内部类导致的.因为非静态的内部类默认会持有外部类的引用
内存泄漏:某一块内存应该被回收,而由于种种原因无法被回收,也就无法再利用此块内存
内存溢出:(OOM)当程序需要分配一块内存来使用的时候,发现所有的内存都被占用,无法分配新的内存空间导致内存溢出(其实就是内存不够用了,因为在移动设备上每个 app 的内存是非常有限的)
1.Handler 引起的内存泄漏
看代码
1 | public class HandlerLeakActivity extends AppCompatActivity { |
代码简介:
代码比较简单,就是一个 activity 中有一个 handler, 并且在onCreate()中handler 发送了一个延迟10min 的消息,但是随后, activity 被 finish 了.
内存泄漏原因:
~~因为有一个延迟消息,还没有被处理, 所以 handler 会一直存在,但又由于 handler 是 activity 的内部类.所以 handler又会持有 外部类HandlerLeakActivity 的 activity .导致 activity 无法被回收,从而引起内存泄漏.
解决办法:
~~1.将 handler 改为 static 这样就不会持有 activity
~~2.当 handler 内部需要持有 activity 的时候采用弱引用的方式
~~3.在 activity 被销毁的时候即在 onDestory() 中及时清除掉未被处理的消息
2.非静态内部类的静态对象引起的内存泄漏
1 | public class StaticLeakActivity extends AppCompatActivity { |
代码简介:
~~有一个内部类 InnerClass, 并且在 onCreate() 中对其进行了初始化操作
内存泄漏原因:
~~同样,因为内部类会持有 activity, 而 InnerClass 的实例却被声明为静态的,因此,InnerClass 的实例生命周期会同 Application 一样.所以,即使 Activity 被 finish 之后,因为 Activity 的一个引用被 static 的 InnerClass 的实例持有,导致无法回销毁,从而引起内存泄漏
解决办法:
~~至于怎么防止内存泄漏的发生,也同样是将 InnerClass 改为 static 让其不持有 Activity 的实例来解决
3.线程引起的内存泄漏
1 | public class ThreadLeakActivity extends AppCompatActivity { |
代码简介:
~~由于AsyncTask和 Runnable 都可以创建一个线程. so 把它放在一起来看.在 onCreate()中分别开启一个 AsyncTask 的线程和一个 Runable 线程,并且的里面都做了一个耗时的操作
内存泄漏原因:
~~其实也是因为内部类的原因,因为在线程中都有耗时的操作,这时即使 Activity 被 finish, 那么由于两个内部类是非静态的.都会持有 Activity 的引用,导致 Activity 无法被回收,从而引起内存泄漏
解决办法:
其实同 Handler 一样
~~1.将内部类 static 化
~~2.当线程内部需要持有外部引用的时候使用弱引用
~~3.及时的 onDestory() 中cancle 掉未完成的任务
4.单例引起的内存泄漏
1 | public class SingletonLeak { |
代码简介:
是一个常用的单例模式.但是单例中需要持有一个 context 的引用
内存泄漏原因:
~~如果在创建单例对象的时候传入的 Activity 类型的 context, 那么由于单例的对象是 static 类型的, so 此对象的生命周期同 Application 一样.导致会一直持有此 Activity的引用,从而导致内存泄漏
解决办法:
~~在代码中已经给出了解决办法,就是通过context.getApplicationContext()
来将 Activity 类型的 context 转化为 Application 类型的 context, 这样单例的生命周期同 Application 类型的 context 的生命周期都是整个应用程序.就不会存在内存泄漏的问题
5.WebView 导致的内存泄漏
1 | public class WebviewLeakActivity extends AppCompatActivity { |
代码简介:
就是一个 简答webview加载了一个网页
内存泄漏原因:
~~因为 webview 加载网页的时候会持有一个 activity,而实验发现当 webview 加载的网页所在的 Activity 被 finish 后, 虽然及时在 onDestory() 中对 webview 进行了释放处理,但是webview 所占用的内存并没有被回收.当此网页的图片等资源比较多时,占用的内存也会同步增大.又由于所占用的内存无法及时被回收,从而导致内存泄漏,可以想象当多次的开关这样的 Activity 的时候,内存泄漏会很多.非常有导致可能 oom 的发生
解决办法:
~~当网页所占用的内存比较大的情况下,考虑将这个 Activity 放入到一个新的进程中来执行,当不在需要的时候及时的来杀死这个进程来释放掉所占用的内存,代码中已有体现