HI,Context!

Context的理解

context的使用场景:

  1. getResources()
  2. StartActivity()
  3. 弹出dialog
  4. inflate布局文件
  5. 。。。。。

总之context贯穿了我们安卓整个开发,自然也就尤为重要。但是,我们是否真的完全理解了Context了呢?其实不然,下面跟我一起看如下几个问题。

  • getBaseContext和getApplication,getApplicationContext的区别?
  • 分别在什么时候我们可以使用getBaseContext和getApplication,getApplicationContext呢?

首先来一张Context的家族谱

context家族族谱.png

下面从Context开始分析

Context,作为整个家族的族长,分量自然是最大的,查看源码的得知Context是一个抽象类。仔细想想这是必须的嘛,根据面向对象的编程思想,组长必须是定义族规的,而并非要事必躬亲的,果然,一群抽象方法袭来。。。

//省略大量代码
    public abstract AssetManager getAssets();

    public abstract Resources getResources();

 //省略大量代码
    public abstract PackageManager getPackageManager();

    public abstract ContentResolver getContentResolver();

    public abstract Looper getMainLooper();

    
    public abstract Context getApplicationContext();
//省略大量代码


呵呵,就问你怕不怕。。
根据这些,我们可以得出结论,context就是定义规则的一个族长,这些规则包括获取资源文件的内容,获取looper,获取PackageManager,当然还有getApplicationContext这个重要的方法了。

getApplicationContext存在在Context中代表什么?代表Activiy,Serviec,Application ,中都可以调用啊,有木有!!!!也就是说getApplicationContext的作用域是最广的了。然而我们却没有看到getBaseContext和getApplication。果断不开心啊!没事,继续往下看!

Contextimpl来了,一看这个名就知道他是context的具体实现了,小样起名也不知道矜持点。。哈哈我们来看一下他的内容,不看不知道啊,这小伙子地道啊,族长的要求都实现了有木有,这里只举与本文相关的getApplicationContext()方法,接好源码

  @Override
   public Context getApplicationContext() {
       return (mPackageInfo != null) ?
               mPackageInfo.getApplication() : mMainThread.getApplication();
   }

看完代码mPackageInfo.getApplication() mMainThread.getApplication();我们分别看源码的实现,这两个方法都会返回一个Application对象,那么返回究竟是那个Application呢?拜托,安卓中一个程序只有一个Application好不好!!!所以我们就可以初步认为getApplicationContext获得的是application对象,而且在安卓中一个程序中只有一个Application对象,嗯get!(如果你想说,都到这了,为什么不看看怎么获取到的applicaion呢,满足你的好奇心),想知道application怎么创建出来的
那只能代码追踪大法。。。
以上那两个途径最后都能追踪到LoadedApk.java文件中(ContextImpl作为context)

  ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
           app = mActivityThread.mInstrumentation.newApplication(
                   cl, appClass, appContext);
           appContext.setOuterContext(app);

好嘛!先搞一个ContextImpl对象,然后利用mInstrumentation来new一个Application,并且把ContextImpl对象传进去。在Instrumentation中(ContextImpl作为context)

  static public Application newApplication(Class<?> clazz, Context context)
           throws InstantiationException, IllegalAccessException, 
           ClassNotFoundException {
       Application app = (Application)clazz.newInstance();
       app.attach(context);
       return app;
   }

好吧,原来Application是反射出来的,有兴趣的同学可以看看activity,其实它也是反射出来的。那么 app.attach(context)是什么?点进方法,

 /* package */ final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }

再点击attachBaseContext,嗯,跳到了ContextWrapper,把ContextImpl传到了ContextWrapper

  protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

再看ContextWrapper

一看名称,嗯,包装类,再一看源码

 
    public Context getBaseContext() {
        return mBase;
    }

    @Override
    public AssetManager getAssets() {
        return mBase.getAssets();
    }

    @Override
    public Resources getResources()
    {
        return mBase.getResources();
    }

    @Override
    public PackageManager getPackageManager() {
        return mBase.getPackageManager();
    }

全是mBase.getXXX,mBase是什么,其实mBase就是刚才传进来的ContextImpl有木有!!,妈蛋,这孙子什么都没干就是调用ContextImpl的方法,哎,不对,我们期待的getBaseContext方法出现了,什么,返回的还是mBase。。。。
最终我们得出结论

public Context getBaseContext() {
        return mBase;
    }

返回的就是一个new出来的ContextImpl

最后还有getapplication了,既然还没出现就接着往下找
看ContextThemeWrapper嗯,theme主题,带主题的ContextWrapper,activity是需要界面的,这个名字好有道理!ctrl+f,没找到,不管继续向下,然后终于到activity,看到这个类就兴奋,,毕竟helloworld就是从它开始的,好吧ctrl+f,终于搜到了getapplication看方法

 public final Application getApplication() {
        return mApplication;
    }

跟想象的一样就是返回一个Application,当然也是,毕竟方法名就是getApplication,难不成还能返回一个textview???

再看Service中,

 public final Application getApplication() {
        return mApplication;
    }

同样是这样。。。

到此,我们达到了我们的目的,找到了getApplicationContext,getApplication,getBaseContext的出处,既然都看完了我们就来回顾一下吧

  • getApplicationContext和getApplication返回结果一样,只是两者作用域不一样,getApplicationContext在所有context子类中都可以使用,getApplication只能在activity,或者service中使用(其实这也满足了大部分要求了)
  • getBaseContext返回的是一个Contextimpl对象
  • 有些布局必须依附在一个父布局中,这时context必须为activity类型的,当然你倔强的用application类型的也不会报错,可能样式加载不出来,毕竟activity是继承ContextThemeWrapper的

另外,抛出一个问题,application和contextimol的区别是什么??

以上就是主要内容了,欢迎大家订正

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,265评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,274评论 1 288
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,087评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,479评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,782评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,218评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,594评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,316评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,955评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,274评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,803评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,177评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,732评论 3 229
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,953评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,687评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,263评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,189评论 2 258

推荐阅读更多精彩内容