(转)Context内存泄漏问题
2015-08-11 10:37
239 查看
今天看了一篇介绍Context的文章,写的不错,里面有一段内容平时开发时候没有注意到,摘抄如下:
在项目中,我们经常会遇到使用单例模式或者静态static变量,虽然使用静态类或者静态变量很方便,但是也潜在很多的内存泄漏问题。
6.1静态资源导致的内存泄漏
你可能遇到以下这段代码:
请问,这段代码有什么问题?乍一看貌似没啥问题,挺好的啊!其实不然,主要的问题在于静态变量drawable这里,我们知道静态变量在整个应用的内存里只保存一份,一旦创建就不会释放该变量的内存,直到整个应用都销毁才会释放static静态变量的内存。可是以上drawable资源是由Context对象来获得,从而静态变量drawable会持有该Context对象的引用,也就意味着如果该Context对应的Activity退出finish掉的时候其实该Activity是不能完全释放内存的,因为静态变量drawable持有该Activity的Context。从而导致该Activity内存无法回收,导致内存泄漏隐患。因为Activity就是Context,所有Context的生命周期和Activity是一样长的,我们希望Activity退出时Context也释放内存,这样才不会导致内存泄漏隐患。那么以上这段代码是不安全的,如果代码必须要使用静态资源怎么办呢?其实我们可以这么修改:
这里我们修改成了使用getApplicationContext去获取App的资源。由上一小节可知getApplicationContext返回的对象是Application的Context,而Application的生命周期和整个应用是一样的,应用启动Application被创建,整个应用退出Application销毁。所以Application的Context的生命周期就是整个应用的生命周期,恰好可以用来获取静态资源。利用Application的Context就不会导致内存泄漏了。
6.2 单例模式导致内存泄漏
相信单例模式对开发者很有诱惑力吧!或多或少在项目中都有用过单例模式。你也可能见过一下这段代码:
同样,以上代码也存在内存泄漏的隐患。因为单例模式使用的是静态类的方式,让该对象在整个应用的内存中保持一份该对象,从而减少对多次创建对象带来的资源浪费。同样的问题:在创建该单例的时候使用了生命周期端的Context对象的引用,如果你是在Application中创建以上单例的话是木有任何问题的。因为Application的Context生命周期是整个应用,和单例的生命周期一样,因此不会导致内存泄漏。但是,如果你是在Activity中创建以上单例的话,就会导致和6.1小节一样的问题—内存泄漏。所以我们同样可以将代码修改成如下:
6.3 总结
以后在使用Context对象获取静态资源,创建单例对象或者静态方法的时候,请多考虑Context的生命周期,一定要记得不要使用Activity的Context,切记要使用生命周期长的Application的Context对象。但是并不是所有情况使用Application的Context对象,比如第4小节,在创建Dialog,View控件的时候都必须使用Activity的Context对象。
转载自:http://blog.csdn.net/feiduclear_up CSDN 废墟的树
在项目中,我们经常会遇到使用单例模式或者静态static变量,虽然使用静态类或者静态变量很方便,但是也潜在很多的内存泄漏问题。
6.1静态资源导致的内存泄漏
你可能遇到以下这段代码:
public class MyCustomResource { //静态变量drawable private static Drawable drawable; public MyCustomResource(Context context) { Resources resources = context.getResources(); drawable = resources.getDrawable(R.drawable.ic_launcher); } }
请问,这段代码有什么问题?乍一看貌似没啥问题,挺好的啊!其实不然,主要的问题在于静态变量drawable这里,我们知道静态变量在整个应用的内存里只保存一份,一旦创建就不会释放该变量的内存,直到整个应用都销毁才会释放static静态变量的内存。可是以上drawable资源是由Context对象来获得,从而静态变量drawable会持有该Context对象的引用,也就意味着如果该Context对应的Activity退出finish掉的时候其实该Activity是不能完全释放内存的,因为静态变量drawable持有该Activity的Context。从而导致该Activity内存无法回收,导致内存泄漏隐患。因为Activity就是Context,所有Context的生命周期和Activity是一样长的,我们希望Activity退出时Context也释放内存,这样才不会导致内存泄漏隐患。那么以上这段代码是不安全的,如果代码必须要使用静态资源怎么办呢?其实我们可以这么修改:
public class MyCustomResource { //静态变量drawable private static Drawable drawable; public MyCustomResource(Context context) { Resources resources = (context.getApplicationContext()).getResources(); drawable = resources.getDrawable(R.drawable.ic_launcher); } }
这里我们修改成了使用getApplicationContext去获取App的资源。由上一小节可知getApplicationContext返回的对象是Application的Context,而Application的生命周期和整个应用是一样的,应用启动Application被创建,整个应用退出Application销毁。所以Application的Context的生命周期就是整个应用的生命周期,恰好可以用来获取静态资源。利用Application的Context就不会导致内存泄漏了。
6.2 单例模式导致内存泄漏
相信单例模式对开发者很有诱惑力吧!或多或少在项目中都有用过单例模式。你也可能见过一下这段代码:
public class CustomManager { private static CustomManager sInstance; public static CustomManager getInstance(Context context) { if (sInstance == null) { sInstance = new CustomManager(context); } return sInstance; } private Context mContext; private CustomManager(Context context) { mContext = context; } }
同样,以上代码也存在内存泄漏的隐患。因为单例模式使用的是静态类的方式,让该对象在整个应用的内存中保持一份该对象,从而减少对多次创建对象带来的资源浪费。同样的问题:在创建该单例的时候使用了生命周期端的Context对象的引用,如果你是在Application中创建以上单例的话是木有任何问题的。因为Application的Context生命周期是整个应用,和单例的生命周期一样,因此不会导致内存泄漏。但是,如果你是在Activity中创建以上单例的话,就会导致和6.1小节一样的问题—内存泄漏。所以我们同样可以将代码修改成如下:
public class CustomManager { private static CustomManager sInstance; public static CustomManager getInstance(Context context) { if (sInstance == null) { sInstance = new CustomManager(context.getApplicationContext()); } return sInstance; } private Context mContext; private CustomManager(Context context) { mContext = context; } }
6.3 总结
以后在使用Context对象获取静态资源,创建单例对象或者静态方法的时候,请多考虑Context的生命周期,一定要记得不要使用Activity的Context,切记要使用生命周期长的Application的Context对象。但是并不是所有情况使用Application的Context对象,比如第4小节,在创建Dialog,View控件的时候都必须使用Activity的Context对象。
转载自:http://blog.csdn.net/feiduclear_up CSDN 废墟的树
相关文章推荐
- vs2013中使用PB DataWindow .net
- 配置RHEV中LINUX 虚拟机使用ACTIVE DIRECTORY(AD域)实现单点登录的方法
- 由于jquery版本差异导致的问题总结
- 二分图匹配模板
- 社説 20150811 日航機墜落30年 安全運航への誓いを新たに
- [HDU 2489] Minimal Ratio Tree 最小树
- hdoj 1863 畅通工程
- 自定义控件的属性attr.xml,declare-styleable,TypedArray
- 设计模式之单例模式
- 浅析android:gravity和android:layout_gravity
- URAL2047 Maths (暴力打表 递推)
- Unity3D 中 点乘和叉乘的应用
- 使用Attribute注册所有特性
- linux按照时间查找文件
- iframe跨域通信
- MyBatis魔法堂:Insert操作详解(返回主键、批量插入)
- 从Hadoop到Spark的架构实践
- CodeForces - 344E Read Time (模拟题 + 二分法)
- SpringMVC框架搭建的几个核心配置
- zepto不支持animate({scrollTop:"100px"})的解决办法