2012-08-22 14 views
10

He examinado Android sources por cuestiones de interés. Lo que encontré es que Context es una clase abstracta con el método abstracto:¿Dónde está el código que se llama cuando llama a getApplicationContext()?

public abstract Context getApplicationContext(); 

El ContextWrapper.java extiende Context.java que dio lugar a la aplicación de getApplicationContext() método:

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

Pero mBase es referencia a un objeto de tipo Context que se inicializa en el constructor ContextWrapper:

public ContextWrapper(Context base) { 
    mBase = base; 
} 

¿Entonces esta referencia mBase se refiere a la clase abstract? Bueno, simplemente no entiendo dónde está el código que se ejecuta cuando llamas al getApplicationContext() desde tu Activity.

+0

¿Entiende la forma abstracta funcionan las clases? Hay alguna clase concreta en alguna parte que 'extiende Context', y ahí es donde se implementa el método. –

+0

Me interesa saber dónde está, entiendo cómo funcionan las clases abstractas. – Eugene

Respuesta

15

Este es un ejemplo interesante de polimorfismo.

Mientras su base extiende Context, tiene que proporcionar una implementación de getApplicationContext(), que en el caso de ContextWrapper es el código que ya ha proporcionado aquí. Existe esta implementación, y the one in ContextImpl.

Es importante tener en cuenta un par de cosas al leer el código que ya ha proporcionado: ContextWrapper sí se extiende Context, pero también tiene un Context como una entrada (que podría ser un ContextWrapper, o una Service, o un Application, o un Activity). ContextWrapper no importa qué tipo es; simplemente sabe que tienen un método getApplicationContext y desea llamar a ese método cuando se le solicite. (Por ejemplo, se podría pasar otra ContextWrapper, pero debido a que dicho ContextWrapper también requeriría un Context en su constructor, que acaba de añadir otro nivel de anidamiento.)

La clase Application extends ContextWrapper llama super(null), lo que significaría que getApplicationContext() haría arroje un NullPointerException si se dejó de esa manera, sin embargo, en ContextWrapper también es configurable por attachBaseContext(Context), y aquí es donde se pone interesante.

Ambos Activity y Application tienen los métodos attach(Context [...other stuff]). Cada uno de ellos llama al attachBaseContext() con el Context pasado.

  • En la clase Instrumentation, encontrará android.app.Instrumentation.newApplication(), donde se crea un ContextImpl, y pasa a un Application.
  • En la clase ActivityThread, encontrará handleBindApplication que crea un ContextImpl que se pasa al Activity como su raíz Context.
  • En la clase LoadedApk, encontrará makeApplication que crea un ContextImpl que se pasa a Application. Here son los lugares a los que se llama.

Así, al final del día, mBase normalmente termina como un ContextImpl.

enlaces potencialmente útil Me miraron al mismo tiempo encontrar todo esto a cabo:

+0

Gracias por su respuesta, Jon. Estoy confundido porque no hay implementación de este método ni en 'Application.java' ni en' Service.java'. ¿Dónde está la implementación? – Eugene

+1

La implementación está en 'ContextWrapper'. La parte clave de la información es que 'mBase' cambia en el tiempo de ejecución cuando se inicializa una actividad o aplicación. –

+0

¡Gracias por una investigación y explicación tan detallada! – Eugene

Cuestiones relacionadas