美文网首页
让人迷惑的context

让人迷惑的context

作者: 李die喋 | 来源:发表于2019-09-27 20:33 被阅读0次

在平常的开发过程中经常会遇到传入context的问题,之前简单的查过一些博客,现在好好的总结一下。

Context是什么

Context可以理解为上下文 环境变量。它

  • 描述应用程序环境的信息,即上下文;
  • 是一个抽象类,有具体类去实现;
  • 通过它可以获取应用程序的资源和类,也包括一些应用级别操作,例如启动一个Activity、发送广播、接收Intent等。

下面是它的一个简易的类继承图:


context

可以看到,ContextImpl和ContextWrapper继承Context,Application、service、Acitvity都是Context的子类。所以我们在Activity中传入参数的时候经常会传入一个this,有的时候也会传入一个xxxActivity.this。传入xxxActivity.this的时候出现在匿名内部类中,因为this代表的是匿名类对象。

ContextImpl真正实现了Context类,Activity和Service没有真正的实现,他们的内部只是包含了一个真实的Context对象而已。也就是在创建Activity和Service的时候会创建一个ContextImpl对象,并赋值到Activity的Context类型变量中。

据统计在Android源码中有七处创建了ContextImpl:

  • PackageInfo.makeApplication()
  • performLaunchActivity()中
  • handleCreateBackupAgent()中
  • handleCreateService()中
  • 2次在handleBinderApplication()中
  • 在attach()方法中

这些会在后面的文章进行分析。

getApplicationContext()和xxxAcitvity.this

之前不清楚为什么在传入context的地方也可以传入activity,现在经过看源码中的继承关系activity是context的子类,因此可以那样传入数据。可以认为在activity中activity和context是一样的。

xxxAcitvity.this指的是当前的Activity对象,getApplicationContext()返回一个Context对象,是当前Application的一个实例。可以理解为他们存在的周期不同,activity对应的context存在于活动的生命周期,所以在两个activity之间的跳转传入的是当前的activity;弹出一个dialog的时候传入的也是当前的activity,它依附于activity而存在。其他的情况,比如数据库的调用等情况用getApplication获取全局的context就可以。

//ContextWrapper中 调用了父类的方法
//Context mBase;
@Override
public Context getApplicationContext() {
    return mBase.getApplicationContext();
}

//ContextImpl中的方法
@Override
public Context getApplicationContext() {
    return (mPackageInfo != null) ?
            mPackageInfo.getApplication() : mMainThread.getApplication();
}

可以看到ContextImpl中的getApplicationContext返回的是Application对象,只不过返回类型为Context。

对于第三方应用来说,一个应用只存在一个Application对象,且通过getApplication和getApplicationContext得到的是同一个对象,两者的区别仅仅是返回类型不同。

一个易于混淆的点

单例模式在日常的开发中是会频繁使用的,我之前都是这样写的:

public class Utils{
    private static Utils INSTANCE;
    private Context mContext;
    
    public Utils(Context context){
        this.mContext = context;
    }
    
    public static Utils getInstance(Context context){
        if(INSTANCE == null){
            synchronized(Utils.class){
                if(INSTANCE == null){
                    INSTANCE = new Utils(context);
                }
            }
        }
    }
}

//在使用的时候会传入一个this
Utils utils = Utils.getInstance(this);

这样的写法会造成内存泄漏。因为这里传入的是Activity的context,这个context在这个地方是个强引用,被静态变量所持有。static变量的生命周期伴随着进程的诞生和销毁,也就是说静态变量伴随了app进程的整个生命周期,由于INSTANCE持有了context,在acticity退出的时候,context没有办法得到释放,就造成了内存泄漏。

解决方法就是this.mContext = context.getApplicationContext()。Application伴随了应用的始终,所以使用Application的context自然就不会造成内存泄漏了。

相关文章

  • 让人迷惑的context

    在平常的开发过程中经常会遇到传入context的问题,之前简单的查过一些博客,现在好好的总结一下。 Context...

  • 让人迷惑的事情

    有一双耐克鞋,非常喜欢,颜色款式,都是我心仪的,几乎是天天穿着,很快,有一个地方有点开线了,想着穿着有点破的...

  • Android中的Context

    转自: http://blog.csdn.net/qinjuning 之前一直被Context的作用迷惑,搞不明白...

  • 人的迷惑

    很想对哪个将行就木的脆弱老人说:谢谢您如果您不对我说,我都会被这迷惑一生,感谢你在精神上拯救了我,幸亏你与我谈论了...

  • 读书也会让人迷惑

    卡耐基在《人性的弱点》这本书说:不要随便批评人,因为那是马蜂窝,被批评的人不会接受别人的批评,还会记恨批评的人。 ...

  • 官方真的让人迷惑

    我是搞不懂官方的想法了 先是老早放出sp蛇剪影但不说明,然后放出“高天原”这个新服,接着放先导片、cg预告,这都搞...

  • 非套路的宁静

    现代城市越来越便捷 同时也越来越多套路 路多了容易让人迷路 偶尔的迷惑或被迷惑 有的迷惑中辩明方向 有的迷惑中丧失...

  • Hook环境下的useContext与class环境下的Cont

    一、回顾class的context 1.context的作用 Context提供了一种方式,能够让数据跨越组件层级...

  • 爱情让人迷惑,婚姻似赌博

    点上一根香烟,将自己困在一个密闭的房间,一根又一根地续着,等到房间仙气飘飘的时候,那个嘴里叼着香烟的人,大概也走到...

  • 一个让人迷惑的人

    近来,晚饭后,只要天上星星亮着,我和老婆总要绕着小区转上几圈。 一来锻炼锻炼脚力,俗话说人老脚先老,只有把身体搞好...

网友评论

      本文标题:让人迷惑的context

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