android开发避免Context引起的内存泄露问题

原文地址

http://blog.csdn.net/adreamer_bj/article/details/52099278

android开发中不可避免要引用到Context对象,但是Context又极易引起内存泄露,所以必须明白Context的引用用法才能写好程序

注意编码时保持几个原则:

不要让生命周期长于Activity的对象持有到Activity的引用
尽量使用Application的Context而不是Activity的Context
尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用

通过以下四种方法获取Context对象

View.getContext,返回当前View对象的Context对象,通常是当前正在展示的Activity对象。
Activity.getApplicationContext,获取当前Activity所在的(应用)进程的Context对象,通常我们使用Context对象时,要优先考虑这个全局的进程Context。
Activity.this 返回当前的Activity实例,如果是UI控件需要使用Activity作为Context对象,但是默认的Toast实际上使用ApplicationContext也可以

找了一些资料,结合实践,看看哪些场景是由于Context对象引起的内存泄露

    public class MyActivity extends Activity{  

        private MyManager mMyManager = null;  
        /* (non-Javadoc) 
         * @see android.app.Activity#onCreate(android.os.Bundle) 
         */  
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            //...layout 初始化  
            mMyManager = new MyManager(this);  
        }  
    public class MyActivity extends Activity{  

        private MyManager mMyManager = null;  
        /* (non-Javadoc) 
         * @see android.app.Activity#onCreate(android.os.Bundle) 
         */  
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            //...layout 初始化  
            mMyManager = new MyManager(this);  
        }  

从上面的代码我们可以看到MyManager是依赖于MyActivity,同时MyActivity也依赖于MyManager,两个类形成了双向依赖关系,也称为圈依赖。

这个时候有的同学担心,这个时候用context作为参数传递到MyManager中,当myactivity被回收之后,会不会导致内存泄漏。本人给出的答案是不会造成内存泄漏的

因为两个类处于圈依赖关系,并且属于双向可到达状态,但是两个类都处于不可达到区域,也就是说除了这两个类之外,再没有第三个类引用这两个类,那么这种情况在GC的时候这两个类是会被同时回收掉的。

那么再换一个写法,我把MyManager改一下

    public class MyManager {  

        private Context mContext = null;  

        private static MyManager mInstance = null;  

        public static MyManager getInstance(Context context) {  
            if (mInstance == null) {  
                synchronized (MyManager.class) {  
                    if (mInstance == null) {  
                        mInstance = new MyManager(context);  
                    }  
                }  
            }  
            return mInstance;  
        }  

        private MyManager(Context context){  
            mContext = context;  
        }  
    }  
public class MyActivity extends Activity{  

    private MyManager mMyManager = null;  
    /* (non-Javadoc) 
     * @see android.app.Activity#onCreate(android.os.Bundle) 
     */  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        //...layout 初始化  
        mMyManager = MyManager.getInstance(this);  
    }  


} 

我把MyManager写成了单例模式,那么这个类的生命周期就伴随整个应用的生命周期了。如果在这个时候android GC了MyActivity,但是由于MyManager仍然引用了MyActiviy(Context),所以MyActivity仍然无法被系统回收,这样就造成内存溢出了,那么这样的问题如何解决呢?我建议使用弱引用,继续上代码:

    public class MyManager {  

        private WeakReference<Context> wr  = null;  

        private static MyManager mInstance = null;  

        public static MyManager getInstance(Context context) {  
            if (mInstance == null) {  
                synchronized (MyManager.class) {  
                    if (mInstance == null) {  
                        mInstance = new MyManager(context);  
                    }  
                }  
            }  
            return mInstance;  
        }  

        private MyManager(Context context){  
            wr = new WeakReference<Context>(context);  
        }  
    }  

如果这个时候系统析构了MyActivity对象,那么也就意味着context对象被置空了,那这个时候MyManager由于引用了context的弱引用,所以不会影响对MyActivity的回收,当然context为null对象,所以Mymanager中用到context来处理业务的时候需要做空判断了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值