android内存泄漏与解决方案
2016-11-16 13:58
417 查看
android内存泄漏与解决方案
2.比如,如果引用context的对象声明周期长于activity的那么最好选用application context代替。
3.应注意handler的使用,一般大家使用的时候采用非静态匿名内部类的使用方式,如果handler长于activity的生命周期时,非静态内部类持有外部类的引用,这时便会造成内存泄漏,我们应该将其写成静态内部类,并弱引用activity对象。
代码示下
4.同样也要注意,非静态内部类的静态实例化对象,然后此静态实例化对象被外部比activity生命周期长的对象所持有同样也会造成内存泄漏问题,这种造成内存泄漏的机制与本文第三条基本相同。我们在不用时应注意要将静态变量置为null,这样便于GC的回收。
5.注意activity被静态集合引用导致activity不能释放。
6.在activity中使用Thread、Timer Tasks、广播接收者、Sensor Manager等要在onDestroy方法中释放掉。
//注册
registerReceiver(mFinishReceiver, filter);
//反注册
unregisterReceiver(mFinishReceiver);
2.ContentObserver的注册与反注册
//注册
getContentResolver().registerContentObserver(uri, true, observer);
//反注册
getContentResolver().unregisterContentObserver(observer);
3.Cursor
Cursor cursor = null;
try{
cursor = mContext.getContentResolver().query(uri,null,null,null,null);
if(cursor != null){
cursor.moveToFirst();
//do something
}
}catch(Exception e){
e.printStatckTrace();
}finally{
if(cursor != null){
cursor.close();
}
}
有一种情况下,我们不能直接将Cursor关闭掉,这就是在CursorAdapter中应用的情况,但是注意,CursorAdapter在Acivity结束时并没有自动的将Cursor关闭掉,因此,你需要在onDestroy函数中,手动关闭。
@Override
protected void onDestroy() {
if (mAdapter != null && mAdapter.getCurosr() != null) {
mAdapter.getCursor().close();
}
super.onDestroy();
}4.Bitmap
Bitmap bit = BitmapFactory.decodeFile(path);
if(bit != null && !bit.isRecycled()) {
bit.recycle();
} 5.File
public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context;
}
public static AppManager getInstance(Context context) {
if (instance != null) {
instance = new AppManager(context);
}
return instance;
}
}
应用场景
android系统为每个应用分配的java object heap都是固定的,如果我们不及时释放废弃资源所占用的内存空间,那么就会使我们的程序运行起来非常卡顿,当超过系统为我们分配的内存空间时,系统就会抛出OOM内存泄漏原因
我们开发者不需要它存在的一些资源,但是因为种种原因,这部分资源不能够被GC回收掉,这便会造成内存泄漏,通俗点讲是“该死不死”,下面我将对这“种种原因”来做一下分析Activity内存泄漏
原因
当activity被废弃销毁时,因为activity中的部分对象还持有对activity的引用,这使得GC没办法对废弃的activity的一个回收。解决方案
1.不要让生命周期长的对象引用activity context,既保证引用activity的对象要与activity本身的生命周期一样长。2.比如,如果引用context的对象声明周期长于activity的那么最好选用application context代替。
3.应注意handler的使用,一般大家使用的时候采用非静态匿名内部类的使用方式,如果handler长于activity的生命周期时,非静态内部类持有外部类的引用,这时便会造成内存泄漏,我们应该将其写成静态内部类,并弱引用activity对象。
代码示下
public class MainActivity extends Activity { private TextView tvHelloWorld; private Button btnSetText; private Handler mHandler = new InternalHandler(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnSetText = (Button) findViewById(R.id.btn_set_text); tvHelloWorld = (TextView) findViewById(R.id.tv_hello_world); btnSetText.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mHandler.post(new Runnable() { @Override public void run() { tvHelloWorld.setText("Runnable"); } }); } }); } private static class InternalHandler extends Handler { private WeakReference<Activity> weakRefActivity; /** * A constructor that gets a weak reference to the enclosing class. We * do this to avoid memory leaks during Java Garbage Collection. */ public InternalHandler(Activity activity) { weakRefActivity = new WeakReference<Activity>(activity); } @Override public void handleMessage(Message msg) { Activity activity = weakRefActivity.get(); if (activity != null) { } } } }同样,AsyncTask内部也是Handler机制,同样也存在相同问题。
4.同样也要注意,非静态内部类的静态实例化对象,然后此静态实例化对象被外部比activity生命周期长的对象所持有同样也会造成内存泄漏问题,这种造成内存泄漏的机制与本文第三条基本相同。我们在不用时应注意要将静态变量置为null,这样便于GC的回收。
5.注意activity被静态集合引用导致activity不能释放。
6.在activity中使用Thread、Timer Tasks、广播接收者、Sensor Manager等要在onDestroy方法中释放掉。
资源文件泄漏
原因
当使用了BraodcastReceiver、ContentObserver、Cursor、Bitmap、File等资源时,当不需要使用时,需要及时释放掉,若没有释放,则会引起内存泄漏。解决方案
1.BraodcastReceiver的注册与反注册//注册
registerReceiver(mFinishReceiver, filter);
//反注册
unregisterReceiver(mFinishReceiver);
2.ContentObserver的注册与反注册
//注册
getContentResolver().registerContentObserver(uri, true, observer);
//反注册
getContentResolver().unregisterContentObserver(observer);
3.Cursor
Cursor cursor = null;
try{
cursor = mContext.getContentResolver().query(uri,null,null,null,null);
if(cursor != null){
cursor.moveToFirst();
//do something
}
}catch(Exception e){
e.printStatckTrace();
}finally{
if(cursor != null){
cursor.close();
}
}
有一种情况下,我们不能直接将Cursor关闭掉,这就是在CursorAdapter中应用的情况,但是注意,CursorAdapter在Acivity结束时并没有自动的将Cursor关闭掉,因此,你需要在onDestroy函数中,手动关闭。
@Override
protected void onDestroy() {
if (mAdapter != null && mAdapter.getCurosr() != null) {
mAdapter.getCursor().close();
}
super.onDestroy();
}4.Bitmap
Bitmap bit = BitmapFactory.decodeFile(path);
if(bit != null && !bit.isRecycled()) {
bit.recycle();
} 5.File
File file = new File("/home/admin/a.txt"); FileOutputStream out = null; try { out = new FileOutputStream(file); file.delete(); while(true){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); } finally { try { if(out!=null) { out.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
单例造成的内存泄漏
原因
单例模式非常受开发者的喜爱,不过使用的不恰当的话也会造成内存泄漏,由于单例的静态特性使得单例的生命周期和应用的生命周期一样长,这就说明了如果一个对象已经不需要使用了,而单例对象还持有该对象的引用,那么这个对象将不能被正常回收,这就导致了内存泄漏。如下这个典例:public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context;
}
public static AppManager getInstance(Context context) {
if (instance != null) {
instance = new AppManager(context);
}
return instance;
}
}
总结
归根结底,内存泄漏问题就是不用的资源仍然占据着内存资源,因为我们不合理的代码结构导致这些被废弃的仍然被持有,GC无法进行回收。也就是我们上面分析的常见的场景,但是我们也要注意static的使用毕竟它是常驻内存的。相关文章推荐
- Android开发——常见的内存泄漏以及解决方案(一)
- Android开发——常见的内存泄漏以及解决方案(二)
- Android 中内存泄漏的原因分析及解决方案
- Android 常见的内存泄漏以及解决方案(一)
- Android 中内存泄漏的原因和解决方案
- Android 常见内存泄漏的解决方案
- Android 中内存泄漏的原因和解决方案
- Android内存泄漏问题分析及解决方案
- [置顶] android内存泄漏总结(总结所有导致内存泄露的可能性及解决方案)
- [置顶] Android开发——常见的内存泄漏以及解决方案(二)
- Android Handler导致内存泄漏的解决方案
- Android:内存溢出和内存泄漏的区别、产生原因以及解决方案
- Android 中内存泄漏的原因分析及解决方案
- Android中常见的内存泄漏及解决方案
- [置顶] Android开发——常见的内存泄漏以及解决方案(一)
- Android内存泄漏的常见场景及解决方案
- Android内存泄漏问题分析及解决方案
- Android 中内存泄漏的原因和解决方案
- Android Handler内存泄漏详解及其解决方案
- android内存泄漏解决方案