Когда вызывается getApplicationContext() класса Application?

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

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

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

Application -> ContextWrapper -> Context

public abstract Context getApplicationContext();

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

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

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

public Application() {
    super(null);
}

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

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

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

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


person CodeWarrior    schedule 22.07.2014    source источник
comment
проверить ContextImpl на выходе grepcode   -  person Blackbelt    schedule 22.07.2014
comment
Да, я видел это. Не могли бы вы уточнить, как это работает?   -  person CodeWarrior    schedule 22.07.2014


Ответы (3)


Я предполагаю, что вопрос скорее в том, "где 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. :)

person matiash    schedule 25.07.2014
comment
Является ли исходный код Android неполным в grepcode, потому что согласно grepcode attach() не упоминается mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;. Источник : grepcode.com/file/repository.grepcode.com/java/ext/ - person CodeWarrior; 25.07.2014
comment
@AndroidWarrior Вы просматриваете версию исходного кода Android Version 2.2 r1.1, выпущенную 30 June 2010. Взгляните на последний код, который опубликован в моем ответе. - person Manish Mulimani; 25.07.2014
comment
@AndroidWarrior В случае сомнений всегда проверяйте android.googlesource.com/platform/ frameworks/base.git/+/master (или, в более общем смысле, android.googlesource.com ), который является официальным репозиторием AOSP. И github, и grepcode являются зеркалами и не всегда полностью синхронизированы. - person matiash; 25.07.2014

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

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

person Manish Mulimani    schedule 24.07.2014

person    schedule
comment
Пожалуйста, уточните свой ответ. Объясните, в чем заключается решение, а не просто вставьте код. - person Luceos; 31.07.2014