2014-07-22 19 views
8

Ho una classe Application in cui ho la precedenza su getApplicationContext().Quando viene chiamato getApplicationContext() della classe Application?

Ho cercato nel codice sorgente Android e non riesco a trovare da dove viene chiamato?

la gerarchia di ereditarietà è:

Application -> ContextWrapper -> Context

public abstract Context getApplicationContext(); 

getApplicationContext() è un metodo astratto in Context classe che viene sovrascritta in ContextWrapper classe.

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

mBase è riferimento a un oggetto di tipo Context che viene inizializzata nel costruttore di ContextWrapper ma secondo costruttore della classe del codice di applicazione passa nullo al costruttore di super() cioè costruttore ContextWrapper.

public Application() { 
    super(null); 
} 

Ora l'unico modo possibile per passare contesto è via:

protected void attachBaseContext(Context base) { 
    if (mBase != null) { 
     throw new IllegalStateException("Base context already set"); 
    } 
    mBase = base; 
} 

ma non c'è nessuna chiamata a questo metodo sia. Per favore aiutami a scoprire che da dove viene chiamato getApplicationContext()?

NOTA: Si prega di non inviare alcun collegamento a tali domande come ho passato attraverso ognuna di esse ma ancora nessuna risposta concreta.

+0

selezionare 'ContextImpl' su grepcode out – Blackbelt

+0

Sì, l'ho visto. Potresti per favore elaborare come funziona? – CodeWarrior

risposta

15

Suppongo che la domanda sia piuttosto "dove èchiamato per l'oggetto Application?"

Vedi Application.java:

/** 
* @hide 
*/ 
/* package */ final void attach(Context context) { 
    attachBaseContext(context); 
    mLoadedApk = ContextImpl.getImpl(context).mPackageInfo; 
} 

Se si va un po 'più in alto nella catena di chiamate, troverete Instrumentation.newApplication() (Instrumentation.java) ed infine LoadedApk.makeApplication() (LoadedApk.java), che sono chiamati come l'applicazione viene avviato:

java.lang.ClassLoader cl = getClassLoader(); 
    ContextImpl appContext = new ContextImpl(); 
    appContext.init(this, null, mActivityThread); 
    app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext); 
    ... 
    mApplication = app; 

in breve, il contesto di base fornita alla classe Application è un esempio ContextImpl, creato proprio in questo metodo.

E, se controlli ContextImpl.getApplicationContext():

@Override 
public Context getApplicationContext() { 
    return (mPackageInfo != null) ? mPackageInfo.getApplication() : mMainThread.getApplication(); 
} 

vedrai che finisce in realtà per chiamare LoadedApk.getApplication() (dal momento che è il mPackageInfoLoadedApk esempio), che è il campo mApplication impostato dal metodo di makeApplication() accennato prima .

In breve, dopo tutto questo è impostato, Application.getApplicationContext() finisce per restituire ... la stessa istanza Application. :)

+0

Il codice sorgente di Android è incompleto in grepcode perché come per grepcode 'attach()' non ha menzione di 'mLoadedApk = ContextImpl.getImpl (context) .mPackageInfo;'. Fonte: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/app/Application.java#70 – CodeWarrior

+1

@AndroidWarrior Stai guardando nella versione del codice sorgente Android 'Versione 2.2 r1.1' che è stata rilasciata il' 30 giugno 2010'. Dai un'occhiata all'ultimo codice che è condiviso nella mia [risposta] (http://stackoverflow.com/a/24933443/2083078). –

+0

@ManishMulimani Sì, l'ho visto :) – CodeWarrior

6

Context viene impostato tramite il metodo setBaseContext, quando un'istanza Activity/Service/Receiver viene creata per la prima volta. Qui è lo stack di chiamate:

ContextWrapper::attachBaseContext < - Application::attach <-Instrumentation::newApplication <-LoadedApk::makeApplication <-ActivityThread::performLaunchActivity || ActivityThread::handleReceiver || ActivityThread::handleCreateService || ActivityThread::handleBindApplication

+0

bella catena lol, difficile da trovare –

0
public class ContactManagerApplication extends Application { 
public static Context context = null; 

@Override 
public void onCreate() { 
    super.onCreate(); 
    Log.d("@gaurav", getApplicationContext()+""); 
    context = getApplicationContext(); 

} 
+0

Si prega di elaborare la risposta. Spiegare qual è la soluzione e non semplicemente incollare il codice. – Luceos