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

233

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

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

а также в

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

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

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

t0mm13b
источник
Это то, что я нашел 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 и выше.

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

CommonSenseCode
источник
как насчет получения ресурсов? Я думаю, тебе лучше добавить это в свой стол. и вы можете получить доступ к ресурсам в контексте приложения.
Амир Зиарати
Мы можем начать деятельность из контекста приложения
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 остается даже после того, как действие получает уничтожены.

user2779311
источник
3

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

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

Дирадж Химани
источник
2

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

Dmobile
источник
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 с контекстом активности, все идет хорошо, и вы можете запустить все действия в одной задаче, что приведет к линейной навигации в обратном стеке.

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

DSoldo
источник