2012-08-22 11 views
10

Ho cercato su Android sources solo per interesse. Quello che ho trovato è che Context è una classe astratta con metodo astratto:Dov'è il codice chiamato quando si chiama getApplicationContext()?

public abstract Context getApplicationContext(); 

Il ContextWrapper.java estende Context.java che ha portato alla realizzazione di getApplicationContext() metodo:

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

Ma mBase è riferimento a un oggetto di tipo Context che è inizializzato nel costruttore ContextWrapper:

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

Quindi questo riferimento mBase si riferisce alla classe abstract? Beh, io non capisco dove è il codice che viene eseguito quando chiami getApplicationContext() dal tuo Activity.

+0

Avete capito come funzionano le classi astratto? C'è qualche classe concreta da qualche parte che "estende Context", ed è qui che il metodo è implementato. –

+0

Sono interessato dove è, ho capito come funzionano le classi astratte. – Eugene

risposta

15

Questo è un esempio interessante di polimorfismo.

Finché il base estende Context, deve fornire un'implementazione di getApplicationContext(), che nel caso del ContextWrapper è il codice che hai fornito qui. C'è questa implementazione e the one in ContextImpl.

E 'importante notare un paio di cose durante la lettura del codice che hai fornito: ContextWrapper si estende Context, ma ci vuole anche un Context come ingresso (che potrebbe essere un ContextWrapper, o un Service, o un Application, o un Activity). ContextWrapper non importa di quale tipo sia; semplicemente sa che hanno un metodo getApplicationContext e vuole chiamarlo quando richiesto. (Ad esempio, potrebbe essere superato un altro ContextWrapper, ma perché detto ContextWrapper richiederebbe anche un Context nel suo costruttore, che sarebbe sufficiente aggiungere un altro livello di nidificazione.)

La classe Application extends ContextWrapper chiama super(null), il che significherebbe che getApplicationContext() sarebbe gettare un NullPointerException se fosse lasciato in quel modo - tuttavia, in ContextWrapper è anche impostabile da attachBaseContext(Context), e questo è dove diventa interessante.

Entrambi Activity e Application hanno metodi attach(Context [...other stuff]). Ognuno di loro chiama attachBaseContext() con il pass-in Context.

  • Nella classe Instrumentation, troverete android.app.Instrumentation.newApplication(), in cui viene creato un ContextImpl, e superato in un Application.
  • Nella classe ActivityThread, si trova handleBindApplication che crea un che viene passato a Activity come radice Context.
  • Nella classe LoadedApk, si trova makeApplication che crea un ContextImpl che viene passato a un Application. Here sono i luoghi in cui è chiamato.

Così, alla fine della giornata, mBase finisce in genere come un ContextImpl.

link potenzialmente utile Ho guardato mentre trovare tutto questo fuori:

+0

Grazie per la risposta, Jon. Sono confuso perché non c'è implementazione di questo metodo né in 'Application.java' nemmeno in' Service.java'. Dov'è l'implementazione? – Eugene

+1

L'implementazione è in 'ContextWrapper'. Il bit di informazioni chiave è che mBase cambia in fase di esecuzione man mano che un'attività o un'applicazione vengono inizializzate. –

+0

Grazie per una ricerca e una spiegazione così dettagliate! – Eugene

Problemi correlati