Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where is the code which is called when you call getApplicationContext()?

Tags:

android

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.

like image 202
Eugene Avatar asked Aug 22 '12 18:08

Eugene


1 Answers

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.

  • In the Instrumentation class, you'll find android.app.Instrumentation.newApplication(), where a ContextImpl is created, and passed into an Application.
  • In the ActivityThread class, you'll find handleBindApplication which creates a ContextImpl that gets passed to the Activity as its root Context.
  • In the 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:

  • Usages of attach
  • Usages of attachBaseContext
like image 101
Jon O Avatar answered Oct 19 '22 04:10

Jon O