Android内存泄露之Context
来源:互联网 发布:怎样查网卡的mac地址 编辑:程序博客网 时间:2024/05/22 03:23
一.概述
最近想研究一下Android中的内存泄露,今天我们先看看最简单而且比较容易发生的一种内存泄露情况,Context泄露,最近也看了几篇文章,下面分析一下:
先作个总结:
1.getApplicationContext()可以取到Application对象,而getContext()通常认为返回Activity对象(当然,事实上并不局限于Activity)。
2.对于Application,从Manifest文件中可以看出一个应用程序一般只有一个application节点。Application其实就是一个应用,即:当前应用程序只要还处于运行状态,那么就可以取到Application对象。
3.Application是一个长引用,Activity是短引用。Application适用于存储那些需要反复读取的对象,比如用户的用户名和密码,应用程序的当前设置等。Activity适用于当前活动窗体,比如显示一个dialog,或新建一个View,传入的context对象就应该是当前Activity,而非Application。
二.分析
1。CallBack对象的引用
先看一段代码
private static Drawable sBackground; protected void onCreate(Bundle state) { super.onCreate(state); TextView label = new TextView(this); label.setText("Leaks are bad"); if (sBackground == null) { sBackground = getDrawable(R.drawable.large_bitmap); } label.setBackgroundDrawable(sBackground); setContentView(label); }
我们重点看下面两行代码
TextView label = new TextView(this);label.setBackgroundDrawable(sBackground)
我们看看setBackgroundDrawable(Drawable background)这个方法内部,有一句代码
background.setCallback(this);
这个this指的是什么呢?因为TextView继承自View,那么我们看看View的结构
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource
从这里我们就可以看出这个this代表的是Drawable.CallBack对象的引用,我们再看这两行代码
TextView label = new TextView(this);label.setBackgroundDrawable(sBackground)
所以说sBackground持有View的引用,View持有Activity的引用,当一个Drawable绑定到了View上,实际上这个View对象就会成为这个Drawable的一个callback成员变量,上面的例子中静态的sBackground持有TextView对象lable的引用,而lable只有Activity的引用,而Activity会持有其他更多对象的引用。sBackground生命周期要长于Activity。当屏幕旋转时,Activity无法被销毁,这样就产生了内存泄露问题。
然后我们去看看Drawable中setCallBack的定义,在Android3.0之前的版本是这样写的。
public final void setCallback(Callback cb) { mCallback = cb;}
从Android3.0之后,谷歌引入弱引用解决了这个问题
public final void setCallback(Callback cb) { mCallback = new WeakReference<Callback>(cb);}
2。单例引起的内存泄露
public class Util { 3. 4. private Context mContext; 5. private static Util sInstance; 6. 7. private Util(Context context) { 8. this.mContext = context; 9. } 10. 11. public static Util getInstance(Context context) { 12. if (sInstance == null) { 13. sInstance = new Util(context); 14. } 15. return sInstance; 16. } 17. 18. //other methods 19. }
在初始化Util类的时候,我们传入了一个context对象,当Activity的生命周期结束的时候,我们的Util类里面还有一个Activity的引用,这样Activity占用的内存就不能被回收,造成了内存泄露,那么如何解决这个问题呢?可以用Util.getInstance(getApplicationContext()); 或Util.getInstance(getApplication()); 代替。
因为Application的生命周期是贯穿整个程序的,所以Util类持有它的引用,也不会造成内存泄露问题
总的来说,要避免Context相关的内存泄露,铭记以下几条:
•不要对Activity(Activity继承自Context)作长期的引用(一个指向Activity的引用与Activity本身有相同的生命周期);
•(如果使用长引用)试着用Application代替Activity;
•如果你不能控制内部类的生命周期,避免使用非静态内部类,应该用静态内部类,并且对里面的Activity作弱引用。该问题的解决方法是:对于外部类,用WeakReference构造静态内部类,同时要在视图根完成,并且它的WeakReference内部类要有一个实例(WeakReference)。
•垃圾回收不是防止内存泄露的保险方式。
- android之Context内存泄露
- Android内存泄露之Context
- 内存泄露之Context泄露
- Android内存泄露问题(一)之context的引用
- Android学习系列--App调试内存泄露之Context篇
- 内存泄露之Context篇(上)
- 内存泄露之Context篇(下)
- App调试内存泄露之Context篇
- App调试内存泄露之Context篇
- App调试内存泄露之Context篇
- 《转载》android context 与内存泄露
- Android context(Application/Activity)与内存泄露
- Android中避免Context引起内存泄露
- Android handler的Context内存泄露
- Android application context/activity context与内存泄露
- Android application context/activity context与内存泄露
- Android application context/activity context与内存泄露(转)
- Android:activity context, application context和内存泄露
- topbar
- 内存分析工具MAT 的使用
- test
- CSS部分要点
- 如何利用GNU Parallel工具在单机上处理百万级数量规模的文件
- Android内存泄露之Context
- 正方教务系统验证码自动识别(非打码平台)
- genymotion 此应用与您的手机不兼容
- 收入成本预算-历程
- linux字符驱动之中断按键
- PAT 1004. 成绩排名 (20)
- 第三届蓝桥杯7放旗子填空题
- Redis简介、Redis安装
- CSS 设置导航菜单文字内容垂直居中