Разница между контекстом активности и контекстом приложения


233

Это поставило меня в тупик, я использовал это в Android 2.1-r8 SDK:

ProgressDialog.show(getApplicationContext(), ....);

а также в

Toast t = Toast.makeText(getApplicationContext(),....);

используя getApplicationContext()сбои как ProgressDialogи Toast.... которые приводят меня к этому вопросу:

Каковы фактические различия между контекстом активности и контекстом приложения, несмотря на то, что они разделяют формулировку «Контекст»?


Это то, что я нашел stackoverflow.com/questions/1561803/… ....
t0mm13b

14
Это должно помочь прояснить некоторые вещи: контекст, какой контекст?
toobsco42

Ответы:


250

Оба они являются экземплярами Context , но экземпляр приложения привязан к жизненному циклу приложения, а экземпляр Activity связан с жизненным циклом действия. Таким образом, они имеют доступ к разной информации о среде приложения.

Если вы читаете документы по адресу getApplicationContext, он отмечает, что использовать его следует только в том случае, если вам нужен контекст, жизненный цикл которого отделен от текущего контекста. Это не относится ни к одному из ваших примеров.

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

Но в целом используйте контекст активности, если у вас нет веских причин не делать этого.


1
Я получил «java.lang.reflect.InvocationTargetException» при использовании getApplicationContext, что интересно, когда я перешел на this, он не аварийно завершает работу и работает должным образом .... так что, если они оба являются экземплярами Context, почему один не работает и другой делает? Надеюсь, эта информация поможет другим ... :) спасибо за ваш быстрый ответ ...
t0mm13b

2
Мне нужно увидеть полную трассировку стека исключений, чтобы иметь возможность что-либо сказать. Однако, как я уже сказал, экземпляры контекста имеют разную информацию. Предположительно, чтобы показать диалог или всплывающее окно на экране, требуется информация о действии, которую имеет только экземпляр действия.
Шерил Саймон

74
Я бы сказал, используйте контекст приложения, если у вас нет веских причин не слишком (например, для диалогов или тостов). Утечки памяти довольно легко встретить, используя контексты активности в разных ситуациях, поэтому лучше быть в безопасности :) android-developers.blogspot.com/2009/01/…
Дори

10
Дейв Смит опубликовал очень хорошую запись в блоге для понимания использования контекста, см. Здесь . Убедитесь, что вы также прочитали комментарии!
ChrLipp

1
Дело в том, что даже Диана Хакборн рекомендует использовать контекст активности. stackoverflow.com/questions/5228160/… Но она, кажется, сама не совсем уверена в этом.
JacksOnF1re

178

Я нашел эту таблицу очень полезной для решения, когда использовать различные типы контекстов:

введите описание изображения здесь

  1. Приложение МОЖЕТ запустить Отсюда Действие, но оно требует создания новой задачи. Это может соответствовать конкретным случаям использования, но может привести к нестандартному поведению бэк-стека в вашем приложении и, как правило, не рекомендуется или считается хорошей практикой.
  2. Это законно, но инфляция будет выполняться с темой по умолчанию для системы, в которой вы работаете, а не с тем, что определено в вашем приложении.
  3. Разрешено, если получатель имеет нулевое значение, которое используется для получения текущего значения липкой трансляции, на Android 4.2 и выше.

Оригинальная статья здесь .



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

Мы можем начать деятельность из контекста приложения
Duy Phan

Статью также можно найти здесь: wundermanthompsonmobile.com/2013/06/context
Lifes

34

Это, очевидно, недостаток дизайна API. Во-первых, Контекст деятельности и Контекст приложения - это совершенно разные объекты, поэтому параметры метода, в которых используется контекст, следует использовать ApplicationContextили Activityнапрямую, а не с использованием родительского класса Контекст. Во-вторых, в документе следует указать, какой контекст использовать или нет явно.


25
Полностью согласен. Google бросил мяч на этом. Это полный беспорядок.
Сорен Бойзен

@ SørenBoisen android sdk - полный беспорядок
CommonSenseCode

Они знают о беспорядке, и они уверены, что изо всех сил пытаются исправить столько, сколько они могут.
Pasignature

15

Я думаю, что ProgressDialogэто связано с тем, что присоединение к действию, которое поддерживает подпрограмму, ProgressDialogпоскольку диалоговое окно не может остаться после уничтожения действия, поэтому его необходимо передать this(ActivityContext), который также уничтожается вместе с действием, тогда как ApplicationContext остается даже после того, как действие получает уничтожены.


3

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

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


2

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


1

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

Вот практический пример того, что означает «нестандартное поведение обратного стека», упомянутое @CommonSenseCode:

Предположим, что у вас есть два приложения, которые взаимодействуют друг с другом, App1 и App2 .

Запустите App2: MainActivity из панели запуска. Затем из MainActivity запустите App2: SecondaryActivity . Там, используя либо контекст действия, либо контекст приложения, обе операции живут в одной задаче, и это нормально (учитывая, что вы используете все стандартные режимы запуска и флаги намерений). Вы можете вернуться к MainActivity с помощью повторного нажатия, и в последних приложениях у вас есть только одна задача.

Предположим теперь, что вы находитесь в App1 и запускаете App2: MainActivity с намерением общего ресурса (ACTION_SEND или ACTION_SEND_MULTIPLE). Затем оттуда попробуйте запустить App2: SecondaryActivity (всегда со всеми стандартными режимами запуска и флагами намерений). Что происходит, это:

  • если вы запустите App2: SecondaryActivity с контекстом приложения на Android <10, вы не сможете запустить все действия в одной задаче . Я пробовал с Android 7 и 8 и SecondaryActivity всегда запускается в новой задаче (я думаю, это потому, что App2: SecondaryActivity запускается с контекстом приложения App2, но вы выходите из App1, и вы не запускали приложение App2 напрямую Может быть, под капотом андроид распознает это и использует FLAG_ACTIVITY_NEW_TASK). Это может быть хорошо или плохо в зависимости от ваших потребностей, для моего приложения было плохо.
    В Android 10 происходит сбой приложения с сообщением
    «Для вызова startActivity () вне контекста Activity требуется флаг FLAG_ACTIVITY_NEW_TASK. Это действительно то, что вам нужно?» ,
    Поэтому, чтобы он работал на Android 10, вы должны использовать FALG_ACTIVITY_NEW_TASK, и вы не можете запустить все действия в одной задаче.
    Как вы можете видеть, поведение отличается между версиями Android, странно.

  • если вы запускаете App2: SecondaryActivity с контекстом активности, все идет хорошо, и вы можете запустить все действия в одной задаче, что приведет к линейной навигации в обратном стеке.

Я надеюсь, что я добавил полезную информацию

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.