Analysis of the reason why calling getApplicationContext in the attachBaseContext method of Application returns null

3363 단어
First look at the source code
Application extends ContextWapper
So when we call Application's getApplicationContext, we actually call ContextWapper's getApplicationContext method as follows
from ContextWapper.java   
    @Override
    public Context getApplicationContext() {
        return mBase.getApplicationContext();
    }
 
mBase is the context passed in when attachBaseContext see the following code
form ContextWapper.java    
protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }
continue to investigate
attachBaseContext is a protected method, which is actually called in the attach of Application.java
from Application.java
    final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }
Find where attach is called
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;
    }
where newApplication is called
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, look at the code above
After generating an app instance and calling attachBaseContext, the app instance is finally pointed to mApplication
Now we know that the context passed in attachBaseContext is actually a ContextImpl instance
We look at the getApplicationContext method of ContextImpl
from ContextImpl.java
    @Override
    public Context getApplicationContext() {
        return (mPackageInfo != null) ?
                mPackageInfo.getApplication() : mMainThread.getApplication();
    }
mPackageInfo is actually LoadedApk look down
from LoadedApk.java
    Application getApplication() {
        return mApplication;
    }
Now I know, in fact, what getApplicaitonContext returns is mApplication
According to the makeApplication method of LoadedApk, you can see it
mApplication is assigned after attachBaseContext, so what you get in attachBaseContext is of course NULL

좋은 웹페이지 즐겨찾기