Android之Contenxt内存泄露
来源:互联网 发布:less.js使用 编辑:程序博客网 时间:2024/05/18 01:16
转载请标明出处:一片枫叶的专栏
android开发者恐怕没有不予Context打交道的了,在android开发体系中它代表的是android的上下文,其实activity,service,application都是Context,在android开发过程中,开发者如果不是非常注意,其实很容易由于Context造成内存泄露。
(一)Drawable引起内存泄露
在Android系统中,当我们进行了屏幕旋转,默认情况下,会销毁掉当前的Activity,并创建一个新的Activity并保持之前的状态。在这个过程中,Android系统会重新加载程序的UI视图和资源。假设我们有一个程序用到了一个很大的Bitmap图像,我们不想每次屏幕旋转时都重新加载这个Bitmap对象,最简单的办法就是将这个Bitmap对象使用static修饰。
private static Drawable sBackground;@Overrideprotected 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);}
但是上面的方法在屏幕旋转时有可能引起内存泄露,无论是咋一看还是仔细看这段代码,都很难发现哪里引起了内存泄露。
当一个Drawable绑定到了View上,实际上这个View对象就会成为这个Drawable的一个callback成员变量,上面的例子中静态的sBackground持有TextView对象lable的引用,而lable只有Activity的引用,而Activity会持有其他更多对象的引用。sBackground生命周期要长于Activity。当屏幕旋转时,Activity无法被销毁,这样就产生了内存泄露问题。
2.3.7及以下版本Drawable的setCallback方法的实现
public final void setCallback(Callback cb) { mCallback = cb;}
好在从4.0.1开始,引入了弱引用处理这个问题,弱引用在GC回收时,不会阻止GC回收其指向的对象,避免了内存泄露问题。
public final void setCallback(Callback cb) { mCallback = new WeakReference<Callback>(cb);}
(二)单例模式引起内存泄露
单例是我们比较简单常用的一种设计模式,然而如果单例使用不当也会导致内存泄露。 比如这样一个例子,我们使用饿汉式初始化单例,AppSettings我们需要持有一个Context作为成员变量,如果我们按照下面的实现其实是有问题。
public class AppSettings { private Context mAppContext; private static AppSettings sInstance = new AppSettings(); //some other codes public static AppSettings getInstance() { return sInstance; } public final void setup(Context context) { mAppContext = context; }}
sInstance作为静态对象,其生命周期要长于普通的对象,其中也包含Activity,当我们进行屏幕旋转,默认情况下,系统会销毁当前Activity,然后当前的Activity被一个单例持有,导致垃圾回收器无法进行回收,进而产生了内存泄露。
解决的方法就是不持有Activity的引用,而是持有Application的Context引用。代码如下修改
public final void setup(Context context) { mAppContext = context.getApplicationContext(); }
- 各种方法返回的Context
通常我们想要获取Context对象,主要有以下几种方法
1). View.getContext,返回当前View对象的Context对象,通常是当前正在展示的Activity对象。
2). Activity.getApplicationContext,获取当前Activity所在的(应用)进程的Context对象,通常我们使用Context对象时,要优先考虑这个全局的进程Context。
3). Activity.this 返回当前的Activity实例,如果是UI控件需要使用Activity作为Context对象,但是默认的Toast实际上使用ApplicationContext也可以。
- 其他内存泄露问题
Android中糟糕的AsyncTask
Android中Handler引起的内存泄露
Google为何这样设计OnSharedPreferenceChangeListener
- 避免内存泄露须谨记
不要让生命周期长于Activity的对象持有到Activity的引用
尽量使用Application的Context而不是Activity的Context
尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用(具体可以查看细话Java:”失效”的private修饰符了解)。如果使用静态内部类,将外部实例引用作为弱引用持有。
垃圾回收不能解决内存泄露,了解Android中垃圾回收机制
- Android之Contenxt内存泄露
- android之Context内存泄露
- Android内存泄露之开篇
- Android 内存泄露之资源
- Android内存泄露之开篇
- Android 内存泄露之------Thread
- Android内存泄露之Context
- Android内存泄露之Handler
- Android内存泄露之Handler
- Android技术之 内存泄露
- Android开发内存泄露之--Handler引起的内存泄露
- Android内存泄露分析之-内存泄露的原因
- Android应用开发之避免内存泄露
- Android App 内存泄露之Thread
- Android App 内存泄露之Handler
- Android App 内存泄露之资源
- Android App 内存泄露之开篇
- Android App 内存泄露之Thread
- linux下eclipse安装及快捷方式创建
- 简单Collection遍历(List,Set,Map)
- windows, linus读取properties配置文件
- Session 用户存储登录信息
- 搜索关键字 搜索出来的关键字显示红色
- Android之Contenxt内存泄露
- Java基础:多线程之线程池
- Android 支付宝支付开发
- Android定位当前城市的实现
- Java Web学习总结(11)——Session使用示例教程
- python引入自定义模块
- 山东省ACM省赛历届试题
- hibernate进阶--一对多映射配置
- Android技术--android屏幕适配详解