简体   繁体   中英

When is getApplicationContext() of Application class called?

I have an Application class in which i override getApplicationContext() .

I've looked in the Android Source code and I'm unable to find from where it's called?

The inheritance hierarchy is:

Application -> ContextWrapper -> Context

public abstract Context getApplicationContext();

getApplicationContext() is an abstract method in Context class which is overridden in ContextWrapper class.

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

mBase is reference to an object of type Context which is initialized in ContextWrapper's constructor but as per the code Application's class constructor passes null to the constructor of super() ie constructor of ContextWrapper .

public Application() {
    super(null);
}

Now the only possible way to pass context is via :

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

but there is no call to this method either. Please help me in finding that from where is getApplicationContext() called then?

NOTE : Please don't post any links to such questions as I've gone through each one of them but still no concrete answer.

I guess the question is rather "where is attachBaseContext() called for the Application object?"

See Application.java :

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

If you go a little further up the call chain, you will find Instrumentation.newApplication() ( Instrumentation.java ) and finally LoadedApk.makeApplication() ( LoadedApk.java ), which are called as the application is being started:

    java.lang.ClassLoader cl = getClassLoader();
    ContextImpl appContext = new ContextImpl();
    appContext.init(this, null, mActivityThread);
    app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
    ...
    mApplication = app;

In short, the base Context supplied to the Application class is a ContextImpl instance, created right in this method.

And, if you check ContextImpl.getApplicationContext() :

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

you'll see that it actually ends up calling LoadedApk.getApplication() (since mPackageInfo is the LoadedApk instance), which is the mApplication field set by the makeApplication() method mentioned before.

In short, after all this is set up, Application.getApplicationContext() ends up returning... the very same Application instance. :)

Context is set through setBaseContext method, when an Activity / Service / Receiver instance is created for the first time. Here is the call stack:

ContextWrapper::attachBaseContext <-- Application::attach <-- Instrumentation::newApplication <-- LoadedApk::makeApplication <-- ActivityThread::performLaunchActivity || ActivityThread::handleReceiver || ActivityThread::handleCreateService || ActivityThread::handleBindApplication

 public class ContactManagerApplication extends Application {
public static Context context = null;

 @Override
public void onCreate() {
    super.onCreate();
    Log.d("@gaurav", getApplicationContext()+"");
    context = getApplicationContext();

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM