Где код, который вызывается при вызове getApplicationContext()?
Я изучил источники Android просто из интереса. Я обнаружил, что Context
абстрактный класс с абстрактным методом:
public abstract Context getApplicationContext();
ContextWrapper.java
продолжается Context.java
что привело к реализации getApplicationContext()
метод:
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
Но mBase
ссылка на объект типа Context
который инициализируется в ContextWrapper
конструктор:
public ContextWrapper(Context base) {
mBase = base;
}
Так это mBase
ссылка относится к abstract
учебный класс? Ну, я просто не понимаю, где находится код, который выполняется при вызове getApplicationContext()
от твоего Activity
,
1 ответ
Это интересный пример полиморфизма.
Пока ваш base
продолжается Context
, он должен обеспечить реализацию getApplicationContext()
который в случае ContextWrapper
это код, который вы предоставили здесь. Есть эта реализация, и одна в ContextImpl
,
При чтении предоставленного вами кода важно отметить несколько моментов: ContextWrapper
сам расширяется Context
, но это также занимает Context
в качестве входа (который может быть ContextWrapper
или Service
или Application
или Activity
). ContextWrapper
не важно, какой это; он просто знает, что у них есть метод getApplicationContext
и он хочет вызвать этот метод, когда его спросят. (Например, это может быть передано другому ContextWrapper
, но потому что сказал ContextWrapper
также потребует Context
в своем конструкторе это просто добавит еще один уровень вложенности.)
Application extends ContextWrapper
классовые звонки super(null)
, что будет означать, что getApplicationContext()
бросил бы NullPointerException
если бы это было оставлено таким образом - однако, в ContextWrapper
это также устанавливается attachBaseContext(Context)
и вот где это становится интересным.
И то и другое Activity
а также Application
есть методы attach(Context [...other stuff])
, Каждый из них называет attachBaseContext()
с передачей Context
,
- в
Instrumentation
класс, вы найдетеandroid.app.Instrumentation.newApplication()
, гдеContextImpl
создается и передается вApplication
, - в
ActivityThread
класс, вы найдетеhandleBindApplication
который создаетContextImpl
который передается вActivity
как его кореньContext
, - в
LoadedApk
класс, вы найдетеmakeApplication
который создаетContextImpl
который передаетсяApplication
, Вот места, которые это называется.
Итак, в конце дня, mBase
как правило, заканчивается как ContextImpl
,
Потенциально полезные ссылки, на которые я смотрел, когда выяснял все это:
- Использование
attach
- Использование
attachBaseContext