Android-内存泄漏巧妙解决
来源:互联网 发布:积分系统数据库设计 编辑:程序博客网 时间:2024/05/19 04:54
内存泄漏
内存泄漏,当资源对象长期(例如Context)被引用,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造成内存泄露。
内存溢出,当对象的内存占用已经超出分配内存的空间大小,这时未经处理的异常就会抛出。
随着现在手机内存硬件环境越来越好,内存溢出的情况已经越来越少,而我们经常要面对的优化问题就是内存泄漏,造成内存泄漏,往往是我们不良的代码习惯,大量的内存泄漏问题会造成应用过度消耗内存,应用耗电等问题。
内存泄漏如何解决
内存泄漏如何解决,网上已经有很多优秀的博文进行解读。
例如 http://blog.csdn.net/u010687392/article/details/49909477
内存泄漏解决技巧
在日常开发中,我们遇到更多内存泄漏的问题,最常见的内存泄漏问题就是,我们经常接入一些SDK,一般情况很多SDK都会需要外部传入一个Listener的实例,这时候就会出现内存泄漏的隐患:
public class MainActivity extends Activity implements TestController.TestListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TestController.getsInstance().setListener(this); TestController.getsInstance().run(); } @Override public void onTest() { } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
我们看到,MainActivity实现了TestController.TestListener接口,这时候相当于TestController持有了MainActivity的引用,如果此时我们按下返回键,回到手机桌面,这时候就出现了应用内存泄漏。借助leakcanary库我们可以看到:
原因分析:
由于TestController内部开启了线程,同时持有着MainActivity的引用,导致MainActivity实例对象无法被释放。
解决思路:
如何解决这种类型的内存泄漏,通常的思路是通过弱引用。当一个对象只有被弱引用指向的时候,那么它就随时会垃圾回收系统回收。
1)TestController内部解决
通常一个SDK内部出现了内存泄漏,我们第一个的想法就是让SDK内部增加解决的方法:
手动释放引用
public class TestController { ... public void setListener(TestListener testListener) { this.mTestListener = testListener; } public void release() { this.mTestListener = null; } ...}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
将对象引用改为弱引用
public class TestController { ... private WeakReference<TestListener> mTestListenerWeakReference; public void setTestListener(TestListener testListener) { this.mTestListenerWeakReference = new WeakReference<TestListener>(testListener); } ...}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
2)TestController外部解决
然而,有时候,我们不能总期待着别人帮我们去解决这个问题,由于时间紧急,我们可能自己去解决这个内存泄漏的问题。最理想的情况是,TestController持有的是一个弱引用,然而我们无法改动TestController内存的代码,这时候,我们还是有思路,可以使得TestController最后还是持有着一个弱引用的。
我们需要一个辅助的Listener,它需要实现TestListener接口,然后,在这个辅助的Listener内部持有TestListener的弱引用
/** * Created by linzewu on 17-2-24. */public class ProxyListener implements TestController.TestListener { private WeakReference<TestController.TestListener> mTestListenerWeakReference; public ProxyListener(TestController.TestListener testListener) { mTestListenerWeakReference = new WeakReference<TestController.TestListener>(testListener); } @Override public void onTest() { if (mTestListenerWeakReference.get() != null) { mTestListenerWeakReference.get().onTest(); } }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
MainActivity还是依旧实现TestListener
public class MainActivity extends Activity implements TestController.TestListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TestController.getsInstance().setListener(new ProxyListener(this)); TestController.getsInstance().run(); } @Override public void onTest() { }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
运行,然后马上按下返回键,这时候,我们看到,不会再有内存泄漏的情况出现了。
实际上,这里相当于实现了一个代理类,它持有Listener的引用,只不过相比于普通的代理类,Listener的引用变成了弱引用,而不是强引用。然而,就是这样小小的改动,就这样巧妙地从外部解决的内存泄漏的问题!
这种思路也是来自的同部门的研发大神bq,只能说学无止境,拜服。
最后demo地址:https://github.com/82367825/leaedMemoryDemo
转载自:http://blog.csdn.net/z82367825/article/details/57096258
- Android-内存泄漏巧妙解决
- Android-内存泄漏巧妙解决
- android studio 解决内存泄漏
- Android内存泄漏定位与解决
- Android内存泄漏终极解决篇
- Android内存泄漏终极解决篇
- Android内存泄漏终极解决篇
- Android内存泄漏终极解决篇
- Android内存泄漏查找和解决
- Android内存泄漏终极解决篇
- 快速定位解决Android内存泄漏
- 快速定位解决Android内存泄漏
- 快速定位解决Android内存泄漏
- 快速定位解决Android内存泄漏
- 快速定位解决Android内存泄漏
- Android内存泄漏,检测,解决,避免
- Android webview内存泄漏问题的解决
- Android 使用RxLifecycle解决RxJava内存泄漏
- 1.12Android 学习+进度之十二-聊天UI升级
- unity多语言功能
- Git学习笔记(二)--团队协作
- Android Wi-Fi Firmware(wcnss)修改方法(以QCOM为平台)
- 洛谷 P2279 [HNOI2003]消防局的设立
- Android-内存泄漏巧妙解决
- Curl 相关参数用法
- [E10]展BOM
- JavaScript DOM编程艺术 第2版pdf
- 深入探讨Java中的异常与错误处理
- 51nod 1293 球与切换器
- 从Outlook导出联系人到VCF文件
- ZCMU—1374
- 高级加密标准AES的工作模式(ECB、CBC、CFB、OFB)