android 内存泄露 原理思考

本文深入探讨Android开发中常见的内存泄露问题,包括Handler、Runnable、AsyncTask等类的不当使用导致的外部类引用问题,以及如何通过静态内部类与弱引用(WeakReference)组合或在Activity销毁时进行内存回收操作来解决内存泄露。

看了这么多年的博客,感觉也应该也做点啥,后期会不间断地整理分享各种知识点,共勉。

1 内存泄露?

① 如果一个对象不被任何引用所指向;
② 还有如果一组对象中只包含互相的引用,而没有来自它们外部的引用;
则该对象会在被GC发现的时候被回收。

2 产生以及处理 样例

Android开发中我们经常见到Handler、Runnable、AsyncTask等类,如果采用非静态内部类|匿名内部类的方式使用的话,都会隐式地持有外部类的引用。
在Java中非静态内部类 | 匿名内部类都默认持有外部类的引用,使用不当的话会使外部类一直被某对象持有引用,从而在其该被GC回收时却不被回收,最终导致了内存泄漏,严重后会出现 卡顿 直至崩溃,给用户带来不好的体验。

为啥会默认持有外部类的引用呢?

想象下,如果不隐式地持有外部类的引用,我们怎么可以在内部任意使用外部类的成员变量以及各种方法呢?所以说java在设计之初就有这种默认的规则。

3 解决思路

搞明白原因后就来思考下解决方案,两个方向:
①java中静态内部类不持有外部引用,采用静态内部类+弱引用(WeakReference)持有外部类实例,这样activity回收时WeakReference中的对象会及时回收。
至于静态内部类持有外部引用,可以从编译后的字节码文件中对比查验下:
源文件:

public class MyClass {
			    private class MyInnerClass {
			        private String innerString;
			        public MyInnerClass( ) {
			        }
			        public MyInnerClass(String innerString ) {
			            this.innerString = innerString;
			        }
			    }
			}

编译后字节码文件:

		class MyClass$MyInnerClass
			{
			  private String innerString;
			  public MyClass$MyInnerClass(MyClass paramMyClass) {}
			  public MyClass$MyInnerClass(MyClass paramMyClass, String paramString)
			  {
			    this.innerString = paramString;
			  }
			}

②代码中做好内存回收操作(把代码逻辑写好)
在销毁Activity service等的时候 停止各种异步队列耗时操作,切断他们之间相互持有引用的线。如线程的话停止掉,或者涉及handler的话,注意ondestory()之前调用removeCallbacksAndMessages(null)方法,移除回收消息队列的消息。

对比样例:

private  static class MyTestHandler extends Handler {
   WeakReference<Activity > mActivityReference;
   MyTestHandler(Activity activity) {
       mActivityReference= new WeakReference<Activity>(activity);
   }
   @Override
   public void handleMessage(Message msg) {
       final Activity activity = mActivityReference.get();
       //注意非空判断
       if (activity != null) {
           ......;
       }
   }
}

像上面只是涉及部分的样例,实际代码中还有很多地方可以做优化来防止内存泄露导致的手机卡顿、cpu耗比占高、过热、直至闪退崩溃。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值