TextVersion_02_内存泄漏
来源:互联网 发布:学生管理系统设计c语言 编辑:程序博客网 时间:2024/05/16 03:42
内存泄漏
内存在使用完之后没有被释放,那么就是内存泄漏
一次两次内存泄漏不会造成什么致命的错误
但是内存泄漏多了之后,小则非常影响性能,大则直接导致内存溢出
什么情况会导致内存泄漏
1.资源释放问题
长期保持某些资源,比如Context,Cursor,IO流的引用,资源得不到释放造成内存泄漏
2.对象内存过大问题
保存了多个耗用内存过大的对象(如 Bitmap、XML文件),造成内存超出限制。
3.static 关键字的使用问题
static是Java中的一个关键字,当用他来修饰成员变量时,那么该变量就属于该类,而不是该类的实例
所以用static修饰的变量,生命周期是很长的
如果用他来引用一些资源耗费过多的实例(Context的情况最多), 就要谨慎对待了
打个比方
public class ClassName{
private static Context mContext;
}
这样的代码是非常危险的
如果把Activity赋值到mContext的话,
就算这个Activity已经onDestroy了,
但是由于仍然有对象保存他的引用,那么这个Activity还是不会被释放
再举个Android官方文档中的栗子
private static Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this); //getApplicationContext
label.setText("Leaks are bad");
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}
我们来看这段代码
先是有一个静态的Drawable sBackground
然后是onCreate方法
然后new了一个TextView,设置了一下Text(...)
然后是判断,如果为sBackground为null
那么sBackground=getDrawable(R.drawable.large_bitmap);
注意了:
这里虽然没有显式的保存Context的引用,
但是,当Drawable与View连接了之后,Drawable就将View设置为一个回调
由于View中是包含了Context的引用的,
所以实际上还是保存了Context的引用
引用链: Drawable--TextView--Context
所以,Context还是没有被释放,发生了内存泄漏
针对static的解决方案
1.尽量避免static成员变量引用资源耗费过多的实例,比如Context
2.Context尽量使用ApplicationContext,因为Application的Context的生命周期很长,
引用它不会出现内存泄漏的问题
3.使用WeakReference代替强引用,比如可以使用WeakReference<Context> mContextReference;
4.线程导致内存泄漏
线程产生泄漏的主要原因
线程产生内存泄露的主要原因在于线程生命周期的不可控
看看一段简单的代码
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new MyThread().start();
}
private class MyThread extends Thread{
@Override
public void run() {
super.run();
//do somthing while(true)
}
}
}
这段代码很平常,我们思考d一个问题:
如果MyThread的run方法是一个很费时的操作,
我们开启这个线程,然后中途我们把设备的横屏变成了竖屏,
一般屏幕转换的时候会重新创建Activity,
我们普遍会认为Activity会被销毁再重建,但是其实不是这样的,
由于我们的线程是Activity的内部类,所以MyThread保存了Activity的一个引用,
当MyThread的run方法没有结束的时候,MyThread是不会被销毁的,所以他引用的这个Activity也不会被销毁
所以就内存泄漏了
有些人喜欢用Android提供的AsyncTask,其实AsyncTask的问题更严重
Thread只有在run方法没结束的时候才出现这种内存泄漏问题
但是AsyncTask内部实现机制运用了ThreadPoolExcutor,
这个类产生的Thread对象的生命周期是不确定的,应用程序都无法控制
所以如果用了AsyncTask作为Activity的内部类,
更容易出现内存泄漏
解决:
1. 把线程的内部类,改成静态内部类(因为非静态内部类拥有外部类对象的强引用,静态类则不拥有)
2. 在线程内部采用弱引用保存Context引用
- TextVersion_02_内存泄漏
- 内存泄漏。。。
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- 内存泄漏
- Scala中的操作符
- 《C++primer》读书笔记四
- C#利用ArrayList生成10个不重复的随机数
- KVO模式 ———满足猥琐大众的 偷窥模式
- Hive学习
- TextVersion_02_内存泄漏
- QQ通信原理
- XML
- utilities(matlab)—— l2row/l2col
- 浅谈C程序的内存分配
- 扣丁音乐(七)——音乐进度条拖动 循环模式 专辑图片倒影功能实现
- java链表 分别用内部类和外部类实现
- WEBService学习
- EventBus使用推荐