getApplication () против getApplicationContext ()

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

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

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


person Matthias    schedule 16.02.2011    source источник
comment
Хороший вопрос. Материал тестирования - это немного загадка (как вы хорошо знаете). Но мне интересно, проявляется ли какая-либо разница в этих двух вызовах методов, если вы не явно создаете объект Application в своем приложении.   -  person Christopher Orr    schedule 16.02.2011


Ответы (4)


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

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

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

Почему вообще существует getApplicationContext()?

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

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

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

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

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

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

person Pierre-Yves Ricau    schedule 20.07.2011
comment
@ Piwaï: Не слушай документ. Подкласс android.app.Application - это супер полная помощь. Например, у меня были бесконечные проблемы с инициализацией базы данных. После переезда в Application.onCreate он работал как шарм. Теперь я выполняю инициализацию всей системы в Application, и я бы не стал писать другое приложение без него. - person Martin; 07.08.2013
comment
@Martin Отказ от прослушивания документации обычно означает, что ваш код может сломаться в будущем или даже сейчас при непредвиденных условиях, потерять переносимость, плохо работать, помешать разработчикам платформы внести полезные изменения (что нарушает предположение, которое вы сделали неправильно, хотя это было основано только на текущей реализации, а не на документации). Я думаю, что это довольно плохое поведение и очень плохой совет. - person Palec; 06.02.2014
comment
@Palec: «Обычно нет необходимости создавать подклассы Application». - Это просто намек. Я по-прежнему использую официально задокументированные функции по назначению. - Вначале я использовал эти «статические синглтоны», и они оказались головной болью… - Ленивая инициализация имеет свои проблемы. Особенно при использовании с контрольно-измерительными приборами. - У меня все еще есть эти синглтоны для модульности, но я создаю их в блоке в onCreate подкласса android.app.Application. - работает как шарм. - person Martin; 06.02.2014
comment
@Martin Я должен был прояснить: моя реакция касалась только первого предложения. «Не слушай документ». Как правило, это очень опасный совет. Но «Это всего лишь намек - в этом случае вы можете проигнорировать документ, если у вас есть причина, и я вам ее покажу…» звучит для меня абсолютно нормально. - person Palec; 06.02.2014
comment
кстати, Джейк Уортон делает это в методе get () github.com/JakeWharton/u2020/blob/master/src/main/java/com/ - person urSus; 01.06.2014
comment
при написании кода в широковещательном приемнике, который не является контекстом, но получает контекст в его методе onReceive, вы можете вызвать только getApplicationContext (). Это также означает, что вам НЕ гарантируется доступ к вашему приложению в BroadcastReceiver. . Итак, что мы можем сделать для доступа к моему классу приложения в BroadcastReceiver? - person Dr.jacky; 18.07.2014
comment
В большинстве случаев статические синглтоны могут обеспечивать ту же функциональность более модульным способом - как можно было бы настроить синглтоны для объекта приложения, не расширяя сам класс приложения и не присваивая его переменной, которая будет возвращена синглтоном? - person Bitcoin Cash - ADA enthusiast; 26.11.2015
comment
Я думаю, что важно добавить к обсуждению @Palec & Martin, что приложение является единственным местом, где следует определять синглтоны в приложении для Android, поскольку традиционный статический синглтон-шаблон основан на согласованных идентификаторах процессов, какая ОС Android не может вам гарантировать. Если вы обнаружите, что ваше приложение ANR после возвращения из долгого сна, вероятно, поэтому; Если это так, вы можете консолидировать свою зависимость от этого шаблона проектирования и, возможно, изучить библиотеку DI, такую ​​как Dagger, которая может организовать и надежно создавать ваши синглтоны (и не синглтоны!) в приложении. - person anthropic android; 01.09.2018
comment
@anthropicandroid Я не думаю, что вы полностью правы, говоря, что приложение - это единственное место, где следует определять синглтоны, потому что все зависит от того, где вы хотите его использовать. Если он исходит от службы, широковещательного приемника или чего-то, что инициирует система Android, то, вероятно, да, но если это только использование в приложении или пользовательском интерфейсе, то можно создавать одиночные копии повсюду. - person Pierre; 02.04.2019

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

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

Действия и службы более конкретно связаны с объектом Application. Я считаю, что полезность этого заключается в том, что вы можете создать и зарегистрировать в манифесте настраиваемый класс, производный от Application, и быть уверенным, что _ 8_ или Service.getApplication() < / a> вернет этот конкретный объект этого конкретного типа, который вы можете преобразовать в производный класс Application и использовать для любой пользовательской цели.

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

person usethe4ce    schedule 01.11.2012

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

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

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

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

person RivieraKid    schedule 16.02.2011
comment
но Application является Context (наследуется от него), и во время выполнения оба метода возвращают один и тот же экземпляр. Так в чем разница? - person Matthias; 16.02.2011
comment
Разница в размахе. Контекст вашего приложения будет действителен намного дольше, чем, скажем, контекст действия, потому что действие может использоваться только в течение очень короткого времени, в то время как ваше приложение может состоять из многих действий. Ваш контекст активности будет действителен, по крайней мере, в течение периода, который начинается, когда начинается первое действие, и заканчивается, когда последнее действие. Все они являются контекстами, но один из них более длительный и не меняется, а другие недолговечны, и разные экземпляры могут иметь разные контексты. - person RivieraKid; 16.02.2011
comment
Я думаю, вы неправильно поняли мой вопрос. Я не прошу разницы между Activity контекстом и Application контекстом. Я размышляю о разнице между Application (который является глобальным уникальным контекстом приложения) и тем, что возвращает getApplicationContext. Последний фактически не работал до Android 1.6; раньше он всегда возвращал null. - person Matthias; 16.02.2011
comment
@Matthias На мой взгляд, это все еще актуально. Контекст вводится (реализуется) самой системой Android, а приложение наследует и расширяет контекст. Класс приложения можно легко смоделировать (как вы сказали), тогда разве можно с уверенностью сказать, что он показывает, что класс приложения делает некоторую магию (в тестовом проекте) для его достижения, возможно, игнорируя внедренный контекст? - person Audrius; 16.02.2011
comment
Приходи еще? Извините, я до сих пор не понимаю, как это ответить на мой вопрос. - person Matthias; 16.02.2011
comment
Сам контекст предоставляется системой Android, поэтому, когда вы используете Context.doStuff (), вы получаете то, что встроено в базовую ОС. С другой стороны, приложение наследует контекст, поэтому может переопределить кучу вещей в нем, верно? Я просто предполагаю, что даже в тестовом проекте Контекст по-прежнему извлекается из ОС, в то время как класс приложения в тестовом проекте отличается от класса в не тестовом проекте, поэтому он может переопределить некоторые члены контекста, чтобы разрешить издевательство и т. Д., Давая вам другой контекст. Имейте в виду, это всего лишь предположение (-. - person Audrius; 16.02.2011

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

person Lenny Porter    schedule 04.05.2011