I have looked into Android sources just out of interest. What I found is that Context
is an abstract class with abstract method:
public abstract Context getApplicationContext();
The ContextWrapper.java
extends Context.java
which led to implementation of getApplicationContext()
method:
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
But mBase
is reference to an object of type Context
which is initialized in ContextWrapper
's constructor:
public ContextWrapper(Context base) {
mBase = base;
}
So this mBase
reference refers to abstract
class?
Well, I just don't understand where is the code which is executed when you call getApplicationContext()
from your Activity
.
This is an interesting example of polymorphism.
As long as your base
extends Context
, it has to provide an implementation of getApplicationContext()
, which in the case of ContextWrapper
is the code you provided here. There's this implementation, and the one in ContextImpl
.
It's important to note a couple of things when reading the code you provided: ContextWrapper
itself extends Context
, but it also takes a Context
as an input (which could be a ContextWrapper
, or a Service
, or an Application
, or an Activity
). ContextWrapper
doesn't care which kind it is; it just knows that they have a method getApplicationContext
and it wants to call that method when asked. (For example, it could be passed another ContextWrapper
, but because said ContextWrapper
would also require a Context
in its constructor, that would just add another level of nesting.)
The Application extends ContextWrapper
class calls super(null)
, which would mean that getApplicationContext()
would throw a NullPointerException
if it were left that way--however, in ContextWrapper
it's also settable by attachBaseContext(Context)
, and this is where it gets interesting.
Both Activity
and Application
have methods attach(Context [...other stuff])
. Each of them calls attachBaseContext()
with the passed-in Context
.
Instrumentation
class, you'll find android.app.Instrumentation.newApplication()
, where a ContextImpl
is created, and passed into an Application
. ActivityThread
class, you'll find handleBindApplication
which creates a ContextImpl
that gets passed to the Activity
as its root Context
.LoadedApk
class, you'll find makeApplication
which creates a ContextImpl
that gets passed to an Application
. Here are the places it's called.So, at the end of the day, mBase
typically ends up as a ContextImpl
.
Potentially useful links I looked at while finding all of this out:
attach
attachBaseContext
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With