美文网首页
Android Context与内存泄漏

Android Context与内存泄漏

作者: Android_冯星 | 来源:发表于2018-12-27 16:41 被阅读0次

    Context

    xt

    Context作用域

    image.png

    使用Context

    通常我们想要获取Context对象,主要有以下四种方法

    1. View.getContext,返回当前View对象的Context对象,通常是当前正在展示的Activity对象。
    2. Activity.getApplicationContext,获取当前Activity所在的(应用)进程的Context对象,通常我们使用Context对象时,要优先考虑这个全局的进程Context。
    3. ContextWrapper.getBaseContext():用来获取一个ContextWrapper进行装饰之前的Context,可以使用这个方法,这个方法在实际开发中使用并不多,也不建议使用。
    4. Activity.this 返回当前的Activity实例,如果是UI控件需要使用Activity作为Context对象,但是默认的Toast实际上使用ApplicationContext也可以。

    getApplication()和getApplicationContext()

    两者的内存地址都是相同的,看来它们是同一个对象.Application本身就是一个Context,所以这里获取getApplicationContext()得到的结果就是Application本身的实例。实际上这两个方法在作用域上有比较大的区别。getApplication()方法的语义性非常强,一看就知道是用来获取Application实例的,但是这个方法只有在Activity和Service中才能调用的到。那么也许在绝大多数情况下我们都是在Activity或者Service中使用Application的,但是如果在一些其它的场景,比如BroadcastReceiver中也想获得Application的实例,这时就可以借助getApplicationContext()方法了。

    Context 数量:

    Context数量=Activity数量+Service数量+1
    很多人都这样计算,这个公式只在单进程应用成立,如果多个进程,Application在每个进程都会单独存在一份实例。所以应该是:
    Context数量 = Activity数量+Service数量+ 应用进程数量

    常见内存泄漏

    1. 错误的包含context的单例模式
    public class Singleton {
        private static Singleton instance;
        private Context mContext;
    
        private Singleton(Context context) {
            this.mContext = context;
        }
    
        public static Singleton getInstance(Context context) {
            if (instance == null) {
                instance = new Singleton(context);
            }
            return instance;
        }
    }
    
    1. Drawable导致内存泄漏

    Drawable被设置到ImageView上的时候,ImageView会将自身设置到Drawable的callback上去,因为View是实现了Drawable.Callback接口, 这样当Drawable需要刷新的时候,可以调用.这个Callback,然后通知View重新绘制该Drawable. 所以引用的正确顺序应该Drawable->View->Context, 是这样导致的泄露

    正确使用Context

    一般Context造成的内存泄漏,几乎都是当Context销毁的时候,却因为被引用导致销毁失败,而Application的Context对象可以理解为随着进程存在的,所以我们总结出使用Context的正确姿势:

    1. 当Application的Context能搞定的情况下,并且生命周期长的对象,优先使用Application的Context。
    2. 不要让生命周期长于Activity的对象持有到Activity的引用。
    3. 尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,如果使用静态内部类,将外部实例引用作为弱引用持有。

    相关文章

      网友评论

          本文标题:Android Context与内存泄漏

          本文链接:https://www.haomeiwen.com/subject/foarlqtx.html