Android 内存泄露总结

关于内存泄露,很多人已经说了很多了。博主在这里就是总结一下工作中遇到的,以及看其他前辈的文章中提到的,用于警示自己的编程,也给大家一个参考。

防止内存泄露情况:

(0) 静态对象的生命周期和进程的生命周期是相同的。

(1) Context 防止任何难以回收的对象,持有Activity 的Context。例如单例中传入了Activity 对象。
解决办法为,可以传入Appliacation的Context。或者利用软引用。

(2)注册的listener 需要在destroy 时取消。即注册某个对象后,需要进行反注册。

(3)Handler引起的内存泄露。
利用Handler post Runnable时,需要在onStop 中removeCallbacks。
重写Handler类时,需要将去设置为静态内部类,这样Handler的生命周期将不会影响页面销毁。handlerMessage需要Activity对象时可以使用弱引用。

(4)Activity中非静态内部类的静态实例,会导致内存泄露。或者非静态内部类持有静态实例。

非静态的内部类和Activity相关,会持有Activity对象。静态对象不被回收,会导致Activity无法回收。
解决办法为:可以把内部类改为静态内部类,这样就不会持有Activity对象了。

(5)资源对象没有被关闭造成内存泄露,例如cursor , outputStream等。

(6)ListView 利用ViewHoulder ,服用ConverView。

(7)是有Bitmap 时可以巧妙利用软引用。

(8)集合类造成内存泄露,全局性的静态属性的集合只有添加,没有删除的操作,会导致内存泄露。需要在适当时机将其清除。

(9)

Vector v = new Vector(10);
    for (int i = 1; i < 100; i++) {
            Object o = new Object();
            v.add(o);
            o = null;   
    }

这种典型的内存泄露代码。仅仅释放本身是不行的,因为Vector 还在引用这个对象,所以需要先将其从集合中删除。

(10)Activity Fragment 中匿名内部类会持有Activity对象,如果这个匿名类的实现对象被传入到了异步线程中,可能会导致内存泄露。需要在适当的时机进行释放。

(11)Activity 中的静态对象防止和页面有关联,例如和某些View有关联等。这就导致静态对象持有当前Activity对象。导致无法回收。

(12)线程造成的内存泄露。Activity 生命周期结束时,线程的内务还没有结束。这样会导致Activity不会被回收。

(13)ConnectivityManager、 WifiManager 等context.getSystemService(Context.CAMERA_SERVICE)会导致内存泄露。
解决办法:getApplicationContext().getSystemService();解决。

(14)webview 也会造成内存泄露,在退出时,需要destroy()。

(15)GridView的滥用。

GridView和ListView的实现方式不太一样。GridView的View不是即时创建的,而是全部保存在内存中的。
比如一个GridView有100项,虽然我们只能看到10项,但是其实整个100项都是在内存中的。
所以在应用程序退出之前,要讲gridView和adapter全部置为null。

(16) 静态资源问题。将静态资源设置到View上。会导致内存泄露。

public class MyCustomResource {
    //静态变量drawable
    private static Drawable drawable;
    private View view;

    public MyCustomResource(Context context) {
        Resources resources = context.getResources();
        drawable = resources.getDrawable(R.drawable.ic_launcher);
        view = new View(context);
        view.setBackgroundDrawable(drawable);
    }
}

//查看setBackgroundDrawable的源代码:
public void setBackgroundDrawable(Drawable background) {
……….
/*此处的this就是当前View对象,而View对象又是有Context对象获得 因此,变量background持有View对象的引用,View持有Context的引用, 所有background间接持有Context对象的引用了/
background.setCallback(this);
…….
}

此处的background.setCallback(this);的this是当前的view的对象。由于background是一个静态变量,会一直持有View对象的引用,而然View对象又是由Context对象创建出来的,因此background会间接持有Context的对象的引用。
所以:
该Context对应的Activity退出finish掉的时候其实该Activity是不能完全释放内存的。
值得注意的是:
代码是由于静态资源drawable持有View对象的引用导致内存泄漏隐患的,并不是由于context.getResource导致内存泄漏,因此如果你想通过context.getApplicaitonContext来获取getResource是解决不了内存泄漏的.

(17) TimerTask对象 TimerTask对象在和Timer的schedule()方法配合使用的时候极容易造成内存泄露。
要在合适的时候进行Cancel即可。

private void cancelTimer(){ 
        if (mTimer != null) { 
            mTimer.cancel(); 
            mTimer = null; 
        } 
        if (mTimerTask != null) { 
            mTimerTask.cancel(); 
            mTimerTask = null; 
        }
    }

(18) Dialog对象:使用isFinishing()判断Activity是否退出。才可以showDialog

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值