2014-07-22 2 views
8

У меня есть класс Application, в котором я переопределяю getApplicationContext().Когда вызывается метод getApplicationContext() класса Application?

Я просмотрел исходный код Android, и я не могу найти, откуда он называется?

Иерархия наследования:

Application -> ContextWrapper -> Context

public abstract Context getApplicationContext(); 

getApplicationContext() является абстрактным методом в Context класса, который переопределен в классе ContextWrapper.

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

mBase является ссылкой на объект типа Context, который инициализируется конструктор ContextWrapper, но в соответствии с конструктором класса кода приложения в нуле переходит в конструктор super() т.е. конструктора ContextWrapper.

public Application() { 
    super(null); 
} 

Теперь единственный возможный способ передачи контекста является:

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

но нет никакого вызова этого метода либо. Пожалуйста, помогите мне найти то, что называется getApplicationContext()?

ПРИМЕЧАНИЕ: Пожалуйста, не оставляйте ссылки на такие вопросы, как я прошел через каждый из них, но до сих пор нет конкретного ответа.

+0

check 'ContextImpl' on grepcode out – Blackbelt

+0

Да, я его видел. Не могли бы вы рассказать, как это работает? – CodeWarrior

ответ

15

Я думаю, что вопрос скорее «где attachBaseContext() вызвал для объекта Application

См Application.java:

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

Если вы идете немного дальше вверх по цепочке вызовов, вы найдете Instrumentation.newApplication() (Instrumentation.java) и, наконец, LoadedApk.makeApplication() (LoadedApk.java), которые называются в качестве приложения в настоящее время начала:

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

Короче говоря, базовый контекст подается в Application класса является ContextImpl экземпляр, созданный прямо в этом методе.

И, если вы проверяете ContextImpl.getApplicationContext():

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

вы увидите, что это на самом деле заканчивается вызовом LoadedApk.getApplication()mPackageInfo является LoadedApk экземпляр), который является mApplication поле устанавливается makeApplication() методом упомянутого выше ,

Короче говоря, после того, как все это настроено, Application.getApplicationContext() заканчивает возвращение ... тем же самым Application экземпляра. :)

+0

Исходный код Android не завершен в grepcode, потому что в соответствии с grepcode 'attach()' не упоминается 'mLoadedApk = ContextImpl.getImpl (context) .mPackageInfo;'. Источник: 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 Вы ищете в версию для Android версии 'Version 2.2 r1.1', которая была выпущена 30 июня 2010 года. Взгляните на последний код, который используется в моем [ответе] (http://stackoverflow.com/a/24933443/2083078). –

+0

@ManishMulimani Да, просто увидел, что :) – CodeWarrior

6

Context устанавливается с помощью метода setBaseContext, когда экземпляр Activity/Service/Receiver создается впервые. Вот стек вызовов:

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

+0

nice chain lol, трудно найти –

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

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

} 
+0

Пожалуйста, уточните свой ответ. Объясните, что такое решение, а не просто вставьте код. – Luceos

Смежные вопросы