Где код, который вызывается при вызове 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,

Потенциально полезные ссылки, на которые я смотрел, когда выяснял все это:

Другие вопросы по тегам