Когда вызывать контекст активности или контекст приложения?
Было много сообщений о том, что представляют собой эти два контекста. Но я по-прежнему не совсем прав.
Как я понимаю до сих пор:
Каждый из них является экземпляром его класса, что означает, что некоторые программисты рекомендуют вам использовать this.getApplicationContext()
как можно чаще, чтобы не "утечка" какой-либо памяти. Это связано с тем, что другой this
(получение контекста экземпляра Activity
) указывает на Activity
, который уничтожается каждый раз, когда пользователь наклоняет телефон или покидает приложение и т.д. Который, по-видимому, сборщик мусора (GC) 't ловить и, следовательно, использует слишком много памяти.
Но может ли кто-нибудь придумать некоторые действительно хорошие примеры кодирования, где было бы правильным использовать this
(получение контекста текущего экземпляра Activity
), а контекст приложения будет бесполезным/неправильным?
Ответы
Ответ 1
getApplicationContext()
почти всегда ошибочно. Г-жа. Hackborn (среди прочего) были очень явными, что вы используете только getApplicationContext()
, когда знаете, почему используете getApplicationContext()
и только тогда, когда вам нужно использовать getApplicationContext()
.
Чтобы быть тупым, "некоторые программисты" используют getApplicationContext()
(или getBaseContext()
, в меньшей степени), потому что их опыт Java ограничен. Они реализуют внутренний класс (например, OnClickListener
для Button
в Activity
) и нуждаются в Context
. Вместо того, чтобы использовать MyActivity.this
для доступа к внешнему классу 'this
, они используют getApplicationContext()
или getBaseContext()
для получения объекта Context
.
Вы используете getApplicationContext()
только тогда, когда знаете, что вам нужен Context
для чего-то, что может жить дольше, чем любая другая вероятная Context
, которую вы имеете в своем распоряжении. Сценарии включают:
-
Используйте getApplicationContext()
, если вам нужно что-то связанное с Context
, которое будет иметь глобальную область видимости. Я использую getApplicationContext()
, например, в WakefulIntentService
, для статического WakeLock
, который будет использоваться для службы. Поскольку это WakeLock
является статическим, и мне нужно Context
, чтобы получить в PowerManager
, чтобы создать его, безопаснее использовать getApplicationContext()
.
-
Используйте getApplicationContext()
, когда вы привязываетесь к 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
остается за время жизни вашего процесса.
Ответ 2
Я думаю, что есть много вещей, которые плохо документированы на сайте SDK, это один из них. Требование, которое я собираюсь сделать, состоит в том, что кажется, что лучше использовать по умолчанию контекст приложения и использовать контекст активности, когда вам действительно нужно. Единственное место, где я когда-либо видел, что вам нужен контекст активности, - это диалог прогресса. SBERG412 утверждает, что вам нужно использовать контекст активности для тоста, но в документах Android четко отображается используемый контекст приложения. Из-за этого примера Google я всегда использовал контекст приложения для тостов. Если это неправильно, тогда Google сбросил мяч здесь.
Здесь больше задуматься и посмотреть:
Для сообщения с тостом руководство Google Dev использует контекст приложения и явно скажет, чтобы использовать его:
Уведомления тоста
В диалоговом окне руководства Dev вы увидите, что AlertDialog.Builder использует контекст приложения, а затем индикатор выполнения использует контекст активности. Это не объясняется Google.
Dialogs
Похоже, что причиной использования контекста приложения является необходимость обрабатывать изменения конфигурации, такие как изменение ориентации, и вы хотите сохранить объекты, которым нужен контекст, например Views. Если вы посмотрите здесь: Изменения времени выполнения
Существует предостережение об использовании контекста активности, который может создать утечку. Этого можно избежать с помощью контекста приложения с представлениями, которые должны быть сохранены (по крайней мере, это мое понимание). В приложении, которое я пишу, я намерен использовать контекст приложения, потому что я пытаюсь придерживаться некоторых взглядов и других вещей при изменении ориентации, и я все еще хочу, чтобы активность была уничтожена и воссоздана при изменении ориентации. Таким образом, я должен использовать контекст приложения, чтобы не вызвать утечку памяти (см. Избегать утечек памяти). Мне кажется, что есть много веских причин использовать контекст приложения вместо контекста активности, и для меня это почти похоже на то, что вы будете использовать его чаще, чем контекст активности. То, что многие книги Android, которые я прошел, похоже, делают, и то, что многие из примеров Google, которые я видел, делают.
Документация Google действительно заставляет задуматься, что использование контекста приложения в большинстве случаев прекраснее, и на самом деле появляется чаще, чем использование контекста активности в их примерах (по крайней мере, примеры, которые я видел). Если это действительно такая проблема для использования контекста приложения, то Google действительно нужно уделять больше внимания этому. Им нужно дать понять, и им нужно переделать некоторые из своих примеров. Я бы не стал обвинять это полностью в неопытных разработчиках, поскольку авторитет (Google) действительно делает его похожим на нецелесообразность использования контекстов приложений.
Ответ 3
Я использовал эту таблицу как руководство для того, когда использовать различные типы контекста, такие как контекст приложения (то есть: getApplicationContext()
) и контекст действия, а также контекст BroadcastReceiver:
![enter image description here]()
Все заслуги идут к оригинальному автору здесь для получения дополнительной информации.
Ответ 4
Какой контекст использовать?
Существует два типа контекста:
-
Контекст приложения связан с приложением и всегда будет таким же на протяжении всего срока службы приложения - он не изменяется. Поэтому, если вы используете Toast, вы можете использовать контекст приложения или даже контекст активности (оба), потому что тост может отображаться из любого места в вашем приложении и не привязан к определенному окну. Но есть много исключений, одно исключение - когда вам нужно использовать или передавать контекст активности.
-
Контекст активности связан с активностью и может быть уничтожен, если действие уничтожено - может быть несколько действий (более чем вероятно) с одним приложением. И иногда вам абсолютно необходим дескриптор контекста активности. Например, если вы запускаете новое действие, вам нужно использовать контекст действия в своем намерении, чтобы новая активность запуска была связана с текущей деятельностью с точки зрения стека активности. Однако вы также можете использовать контекст приложения для запуска нового действия, но тогда вам нужно установить флаг Intent.FLAG_ACTIVITY_NEW_TASK
в намерении рассматривать его как новую задачу.
Рассмотрим некоторые случаи:
-
MainActivity.this
относится к контексту MainActivity, который расширяет класс Activity, но базовый класс (активность) также расширяет класс Context, поэтому его можно использовать для контекста активности.
-
getBaseContext()
предлагает контекст активности.
-
getApplication()
предлагает контекст приложения.
-
getApplicationContext()
также предлагает контекст приложения.
Для получения дополнительной информации, пожалуйста, проверьте .
Ответ 5
Мне было интересно, почему бы не использовать Application Context для каждой операции, которую он поддерживает. В конце он снижает вероятность утечки памяти и пропускает нулевую проверку для getContext() или getActivity() (при использовании контекста вложенного приложения или полученного через статический метод из приложения). Заявления, например, Г-жа. Hackborn использовать контекст приложения только в случае необходимости, не кажутся убедительными для меня без объяснения причин. Но кажется, что я нашел ответ, почему:
обнаружили, что в некоторых версиях Android/устройствах есть проблемы, которые не соответствуют этим правилам. Например, если у меня есть BroadcastReceiver, которому передан Контекст, и я конвертирую этот Контекст в Контекст приложения, а затем пытаюсь вызвать registerReceiver() в Контексте Приложения, есть много случаев, когда это работает отлично, но также и во многих случаях, когда я получаю авария из-за исключения ReceiverCallNotAllowedException. Эти сбои происходят в широком диапазоне версий Android от API 15 до 22. https://possiblemobile.com/2013/06/context/#comment-2443283153
Поскольку это не гарантировало, что все операции, описанные как поддерживаемые Контекстом приложений в приведенной ниже таблице, будут работать на всех устройствах Android!
![введите описание изображения здесь]()
Ответ 6
Два замечательных примера использования контекста Activity и контекста приложения - это отображение либо сообщения Toast, либо встроенного диалогового сообщения, так как использование контекста приложения вызывает исключение:
ProgressDialog.show(this, ....);
или
Toast t = Toast.makeText(this,....);
Обе из них нуждаются в информации из контекста Activity, который не указан в контексте приложения.
Ответ 7
Контекст приложения активен до тех пор, пока ваше приложение не будет доступно только, и оно не зависит от цикла жизненного цикла, но контекст сохраняет объект долговечным. Если объект, который вы используете временно, в это время использует Контекст приложения и Контекст активности, используется полностью oposite контекста приложения.