Application的attachBaseContext方法中调用getApplicationContext返回null的原因分析

首先看源码 

Application extends ContextWapper

所以当我们在调用Application的 getApplicationContext时 实际上调用的是 ContextWapper的getApplicationContext 方法如下

from ContextWapper.java   
    @Override
    public Context getApplicationContext() {
        return mBase.getApplicationContext();
    }

mBase 就是 attachBaseContext 时传入的context 看如下代码

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

再继续追查

attachBaseContext 是一个 protected 方法  他其实是在Application.java 的attach 中调用

from Application.java
    final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }

查找attach 调用的地方  

from Instrumentation.java
 public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }

newApplication 的调用处

from LoadedApk.java    
public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }
        ......................................
        try {
            java.lang.ClassLoader cl = getClassLoader();
        .....................................
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {

        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
        .................................
        return app;
    }

OK 看上面这个代码 

生成app实例 并且调用了 attachBaseContext 之后 最终将app实例指向了 mApplication

现在我们知道了 attachBaseContext 中传入的 context 其实是个 ContextImpl 实例

我们查看ContextImpl 的 getApplicationContext方法

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

mPackageInfo 其实就是LoadedApk 往下看

from LoadedApk.java
    Application getApplication() {
        return mApplication;
    }

现在知道了 其实getApplicaitonContext 返回的就是mApplication

根据LoadedApk的makeApplication方法里面可以看到

mApplication 是在attachBaseContext 之后 才被赋值的 ,所以你在attachBaseContext 里面去拿 拿到的当然是NULL了

发布了24 篇原创文章 · 获赞 3 · 访问量 6136

猜你喜欢

转载自blog.csdn.net/binghelonglong123/article/details/92796046