getApplicationContext()
почти всегда неправильно. Г-жа Хэкборн (среди прочих) очень четко заявляла, что вы используете толькоgetApplicationContext()
тогда, когда знаете, почему вы используете, getApplicationContext()
и только когда вам нужно использовать getApplicationContext()
.
Чтобы быть грубым, «некоторые программисты» используют getApplicationContext()
(или getBaseContext()
, в меньшей степени), потому что их опыт Java ограничен. Они реализуют внутренний класс (например, a OnClickListener
for Button
in in Activity
) и нуждаются в Context
. Вместо того, чтобы использовать MyActivity.this
для доступа к внешнему классу this
, они используют getApplicationContext()
или getBaseContext()
для получения Context
объекта.
Вы используете толькоgetApplicationContext()
тогда, когда знаете, что вам нужно Context
что-то, что может жить дольше, чем любой другой, Context
который у вас есть в вашем распоряжении. Сценарии включают в себя:
Используйте, getApplicationContext()
если вам нужно что-то привязанное к тому, Context
что само по себе будет иметь глобальную область видимости. Я использую getApplicationContext()
, например, WakefulIntentService
для статического, WakeLock
который будет использоваться для службы. Так как это WakeLock
статично, и мне нужно Context
получить, PowerManager
чтобы создать его, его безопаснее всего использовать getApplicationContext()
.
Используйте, getApplicationContext()
когда вы связываете с a Service
из Activity
, если вы хотите передать ServiceConnection
(т.е. дескриптор привязки) между Activity
экземплярами через onRetainNonConfigurationInstance()
. Android внутренне отслеживает привязки через них ServiceConnections
и содержит ссылки на те, Contexts
которые создают привязки. Если вы выполняете привязку из Activity
, то у нового Activity
экземпляра будет ссылка на тот, у ServiceConnection
которого есть неявная ссылка на старый Activity
, а старый Activity
не удастся собрать.
Некоторые разработчики используют собственные подклассы Application
для своих собственных глобальных данных, через которые они получают getApplicationContext()
. Это конечно возможно. Я предпочитаю статические члены данных, если только по какой-либо причине у вас может быть только один пользовательский Application
объект. Я создал одно приложение, используя пользовательский Application
объект, и нашел, что это больно. Мисс Хакборн также согласна с этой позицией .
Вот причины, почему бы не использовать getApplicationContext()
везде, где вы идете:
Это не полный Context
, поддерживающий все, что Activity
делает. Различные вещи, которые вы попытаетесь сделать с этим Context
, потерпят неудачу, в основном связанные с графическим интерфейсом .
Это может привести к утечкам памяти, если Context
from getApplicationContext()
удерживает что-то созданное вашими вызовами, которые вы не очистите. С помощью Activity
, если он что-то держит, как только Activity
мусор соберется, все остальное тоже вылетает. Application
Объект остается в течение всей жизни процесса.
getApplicationContext()
тогда, когда вы точно знаете, зачем вам это нужно в данной ситуации. Раздувать макет? Используйте активность. Привязка к сервису, где вам нужна эта привязка, чтобы пережить изменение конфигурации? ИспользуйтеgetApplicationContext()
, чтобы привязка не была привязана кActivity
экземпляру.Я думаю, что есть много вещей, которые плохо документированы на сайте SDK, это один из них. Я утверждаю, что кажется, что по умолчанию лучше использовать контекст приложения и использовать контекст активности только тогда, когда это действительно необходимо. Единственное место, где я когда-либо видел, что вам нужен контекст активности, - это диалог прогресса. SBERG412 утверждает, что вы должны использовать контекст активности для всплывающего сообщения, однако в документах Android четко показан используемый контекст приложения. Я всегда использовал контекст приложения для тостов из-за этого примера Google. Если это неправильно, Google бросил мяч здесь.
Вот еще, чтобы подумать и рассмотреть:
Для сообщения о тостах руководство по разработке Google использует контекст приложения и прямо говорит, что нужно его использовать: Уведомления о тостах
В разделе диалогов руководства по разработке вы видите, что AlertDialog.Builder использует контекст приложения, а затем индикатор выполнения использует контекст действия. Это не объясняется Google. Диалоги
Кажется, что хорошая причина использовать контекст приложения - это когда вы хотите обрабатывать изменения конфигурации, например, изменение ориентации, и вы хотите сохранить объекты, которым нужен контекст, такой как Views. Если вы посмотрите здесь: Изменения во время выполнения Существует осторожность при использовании контекста активности, который может вызвать утечку. Этого можно избежать с помощью контекста приложения с представлениями, которые должны быть сохранены (по крайней мере, это мое понимание). В приложении, которое я пишу, я намерен использовать контекст приложения, потому что я пытаюсь удерживать некоторые представления и другие вещи при изменении ориентации, и я все еще хочу, чтобы действие было уничтожено и воссоздано при изменении ориентации. Таким образом, я должен использовать контекст приложения, чтобы не вызвать утечку памяти (см. Предотвращение утечек памяти). Мне кажется, что есть много веских причин использовать контекст приложения вместо контекста активности, и мне кажется, что вы будете использовать его чаще, чем контекст активности. Это то, что многие книги по Android, которые я просмотрел, похоже, делают, и это то, что делают многие примеры Google, которые я видел.
Документация Google действительно создает впечатление, что использование контекста приложения в большинстве случаев прекрасно, и на самом деле это происходит чаще, чем использование контекста активности в их примерах (по крайней мере, в тех примерах, которые я видел). Если использование контекста приложения на самом деле является такой проблемой, то Google действительно нужно уделять больше внимания этому. Им нужно прояснить это, и они должны переделать некоторые из своих примеров. Я бы не стал винить в этом неопытных разработчиков, поскольку авторитет (Google) действительно заставляет его выглядеть так, будто это не проблема использовать контексты приложения.
источник
Я использовал эту таблицу как руководство для того, когда использовать различные типы контекста, такие как контекст приложения (то есть:)
getApplicationContext()
и контекст действия , а также контекст BroadcastReceiver :Все заслуги идут к оригинальному автору здесь для получения дополнительной информации.
источник
Существует два типа контекста:
Контекст приложения связан с приложением и всегда будет одинаковым на протяжении всего жизненного цикла приложения - он не меняется. Поэтому, если вы используете Toast, вы можете использовать контекст приложения или даже контекст активности (оба), потому что toast может отображаться в любом месте вашего приложения и не привязан к конкретному окну. Но есть много исключений, одно исключение, когда вам нужно использовать или передавать контекст действия.
Контекст действия связан с действием и может быть уничтожен, если действие уничтожено - может быть несколько действий (более чем вероятно) с одним приложением. А иногда вам абсолютно необходим дескриптор контекста активности. Например, если вы запускаете новое действие, вам нужно использовать контекст действия в его намерении, чтобы новое действие запуска было связано с текущим действием с точки зрения стека действий. Тем не менее, вы также можете использовать контекст приложения для запуска нового действия, но тогда вам нужно установить флаг,
Intent.FLAG_ACTIVITY_NEW_TASK
чтобы рассматривать его как новую задачу.Давайте рассмотрим несколько случаев:
MainActivity.this
относится к контексту MainActivity, который расширяет класс Activity, но базовый класс (активность) также расширяет класс Context, поэтому его можно использовать для предложения контекста активности.getBaseContext()
предлагает контекст деятельности.getApplication()
предлагает контекст приложения.getApplicationContext()
также предлагает контекст приложения.Для получения дополнительной информации, пожалуйста, проверьте эту ссылку .
источник
downloadmanager
, и когда готовый сигнал получен, должно отображаться диалоговое окно, например «Что вы хотите сделать с этой загрузкой?». Мое (хакерское) решение сохраняет самое последнееActivity
вstatic
Application
классе и запрашивает текущее,Activity
когда загрузка завершена. Однако я сомневаюсь, что это правильная реализация. TL; DR Как отобразить AlertDialog в любом месте приложения?Мне было интересно, почему бы не использовать Application Context для каждой операции, которую он поддерживает. В конце концов, это снижает вероятность утечки памяти и пропускает нулевую проверку для getContext () или getActivity () (при использовании внедренного контекста приложения или при получении статическим методом из Application). Утверждения, подобные мисс Хакборн об использовании контекста приложения только в случае необходимости, не кажутся мне убедительными без объяснения причин. Но, похоже, я нашел несогласных, почему:
Потому что не гарантируется, что все операции, описанные как поддерживаемые контекстом приложения в таблице ниже, будут работать на всех устройствах Android!
источник
Два замечательных примера использования контекста «Активность» по сравнению с контекстом приложения - при отображении сообщения Toast или встроенного диалогового окна, поскольку использование контекста приложения вызовет исключение:
или
Оба из них нуждаются в информации из контекста действия, которая не предоставляется в контексте приложения.
источник
Контекст приложения жить до тех пор пока ваше приложение живо только и это не зависит от деятельности жизненного цикла , но, контекст объекта держать долгоживущие . Если объект, который вы используете временно, тогда использует контекст приложения и контекст действия, который полностью противоположен контексту приложения.
источник