Reputation: 5176
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()
i.e. 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.
Upvotes: 12
Views: 11505
Reputation: 664
public class ContactManagerApplication extends Application {
public static Context context = null;
@Override
public void onCreate() {
super.onCreate();
Log.d("@gaurav", getApplicationContext()+"");
context = getApplicationContext();
}
Upvotes: 0
Reputation: 55340
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. :)
Upvotes: 22
Reputation: 17615
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
Upvotes: 6