GetApplication() и getApplicationContext()

Я не мог найти удовлетворительного ответа на этот вопрос, поэтому мы идем: что сделка с Activity/Service.getApplication() и Context.getApplicationContext()?

В нашем приложении оба возвращают один и тот же объект. Тем не менее, в ActivityTestCase, насмехаясь над приложением, getApplication() возвращается с макетом, но getApplicationContext все равно будет возвращать другой экземпляр контекста (один из которых вводится Android). Это ошибка? Это специально?

Я даже не понимаю разницы в первую очередь. Существуют ли случаи вне тестового набора, где оба вызова могут возвращаться с разными объектами? Когда и почему? Более того, почему getApplication определяется на Activity и Service, но не на Context? Должен ли всегда существовать допустимый экземпляр приложения из любого места?

Ответ 1

Очень интересный вопрос. Я думаю, что это в основном смысловое значение, а также может быть связано с историческими причинами.

Хотя в текущих реализациях Android и сервисов getApplication() и getApplicationContext() возвращают один и тот же объект, нет никакой гарантии, что это всегда будет иметь место (например, в конкретной реализации поставщика).

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

Почему getApplicationContext() существует в первую очередь?

getApplication() доступен только в классе Activity и в классе Service, тогда как getApplicationContext() объявляется в классе Context.

Это на самом деле означает одно: при написании кода в широковещательном приемнике, который не является контекстом, но ему предоставляется контекст в его методе onReceive, вы можете только вызвать getApplicationContext(). Это также означает, что у вас не гарантируется доступ к вашему приложению в BroadcastReceiver.

Когда вы смотрите на код Android, вы видите, что при подключении активность получает базовый контекст и приложение, а это разные параметры. getApplicationContext() делегирует вызов на baseContext.getApplicationContext().

Еще одна вещь: в документации говорится, что в большинстве случаев вам не нужно подклассы Application:

Как правило, нет необходимости в подклассе Application. В большинстве случаев статические синглтоны могут обеспечивать такую же функциональность более модульным способом. Если вашему singleton нужен глобальный контекст (например, для регистрации широковещательных приемников), функции для его получения может быть предоставлен Context который внутренне использует Context.getApplicationContext() при первом построении синглета.

Я знаю, что это не точный и точный ответ, но все же это отвечает на ваш вопрос?

Ответ 2

Сравните getApplication() и getApplicationContext().

getApplication возвращает объект Application, который позволит вам управлять состоянием вашего глобального приложения и реагировать на некоторые ситуации устройства, такие как onLowMemory() и onConfigurationChanged().

getApplicationContext возвращает глобальный контекст приложения - отличие от других контекстов заключается в том, что, например, контекст активности может быть уничтожен (или иным образом недоступен) для Android, когда ваша активность заканчивается. Контекст приложения остается доступным все время, пока существует ваш объект приложения (который не привязан к конкретному Activity), поэтому вы можете использовать его для таких вещей, как Notifications, которые требуют контекста, который будет доступен для более длительных периодов и не зависит от временных объектов пользовательского интерфейса.

Я думаю, это зависит от того, что делает ваш код, могут ли они быть или не быть одинаковыми - хотя при нормальном использовании я ожидал бы, что они будут разными.

Ответ 3

Кажется, что это связано с оберткой контекста. Большинство классов, полученных из Context, на самом деле являются ContextWrapper, которые по существу делегируют другой контекст, возможно с изменениями обертки.

Контекст - это общая абстракция, которая поддерживает насмешку и проксирование. Поскольку многие контексты привязаны к объекту с ограниченным сроком жизни, например Activity, должен быть способ получить более продолжительный контекст для таких целей, как регистрация для будущих уведомлений. Это достигается Context.getApplicationContext(). Логическая реализация - вернуть глобальный объект Application, но ничто не мешает реализации контекста возвращать обертку или прокси с подходящим временем жизни.

Действия и службы более конкретно связаны с объектом Application. Полезность этого, я считаю, заключается в том, что вы можете создать и зарегистрировать в манифесте пользовательский класс, полученный из Application, и быть уверенным, что Activity.getApplication() или Service.getApplication() вернет этот конкретный объект этого конкретного типа, который вы можете применить к вашему производному классу Application и использовать для любых пользовательских целей.

Другими словами, getApplication() гарантированно возвращает объект Application, тогда как getApplicationContext() может вместо этого возвращать прокси.

Ответ 4

Чтобы ответить на вопрос, getApplication() возвращает объект Application, а getApplicationContext() возвращает объект Context. Основываясь на ваших собственных наблюдениях, я бы предположил, что Контекст обоих идентичен (т.е. За кулисами класс Application вызывает последнюю функцию для заполнения контекстной части базового класса или имеет место какое-то эквивалентное действие). Не важно, какую функцию вы вызываете, если вам нужен только контекст.