内存优化(内存泄露,内存抖动,内存溢出)
内存泄露 memory leak
原因:
没有回收资源
一个程序中,已经不需要使用某个对象,但是因为仍然有引用指向它,垃圾回收器就无法回收它,当该对象占用的内存无法被回收时,就容易造成内存泄露。多个内存泄漏最终会导致内存溢出,即OOM。memory leak会最终会导致out of memory!
解决办法:在不需要的时候及时释放掉资源
handler
static : 释放快
WeakReference:等到handler处理完全后再释放内存
一种是业务逻辑上,在activity销毁的时候移除所有未执行的任务。
一种是从GC上,通static的Handler或者弱引用解决。但是单独的使用弱引用性能不是太高。
private static class UIHndler extends android.os.Handler {
WeakReference<MainActivity> weak;
public UIHndler(MainActivity object) {
weak = new WeakReference<>(object);
}
...
}
AsyncTask
AsyncTask 引起的泄露是由于它本身会持有外部的类对象,也就是activity,所以当activity销毁后,这个线程继续持有这个activity的引用,所以activity不会被销毁,直到线程执行完成。解决方法是自定义静态的AsyncTask类,还有保持AsyncTask与activity的生命周期同步,在antivitg 结束时,把AsyncTask销毁掉。
非静态内部类创建静态实例造成的内存泄漏
静态实例会有外部的引用,导致该Activity不能正常回收,造成内存泄露
public class MainActivity extends AppCompatActivity {
private static TestResource mResource = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(mManager == null){
mManager = new TestResource();
}
//...
}
class TestResource {
//...
}
}
关闭资源,删除监听器,释放内存,
使用了BroadcastReceiver,ContentObserver,File,游标Cursor,Stream,Bitmap等资源的使用,应该在Activity销毁时关闭。
addXXXListener()等方法来增加监听器,但往往释放对象的时候却没有记住去删除这些监听器,从而增加了内存泄漏的机会
Bitmap调用recycle()释放内存。
构造Adapter时,使用缓存的convertView。
连接
数据库连接(dataSourse.getConnection()),网络连接(socket)和io连接。除非其显示的调用了其close()方法将其连接关闭,否则是不会自动被GC回收的。try里面去连接,在finally里面释放连接。
单例造成的内存泄漏
尽量用Application的Context,尽量不要用Activity的context
线程造成的内存泄漏
内存抖动
内存抖动 指内存频繁地分配和回收
后果
1、频繁的GC会导致卡顿
2、严重时还会导致OOM
注:内存抖动为什么会引起OOM呢?
主要原因还是有因为大量小的对象频繁创建,导致内存碎片,从而当需要分配内存时,虽然总体上还是有剩余内存可分配,而由于这些内存不连续,导致无法分配,系统直接就返回OOM了。
解决方案
1、尽量避免在循环体内创建对象,应该把对象创建移到循环体外
2、避免在View的onDraw()方法里频繁地创建对象
3、对于能够复用的对象,可以使用对象池将它们缓存起来
内存溢出
内存溢出 指应用申请超过阈值的内存空间
产生原因
1、应用存在内存泄露,长时间积累导致OOM
2、应用的某些逻辑操作疯狂的消耗掉大量内存
解决方案
1、规避内存泄漏
2、图片进行压缩显示或局部显示