В чем разница между getContext()
, getApplicationContext()
, getBaseContext()
и "this
"?
Хотя это простой вопрос, я не могу понять основную разницу между ними. Если возможно, приведите несколько простых примеров.
В чем разница между getContext()
, getApplicationContext()
, getBaseContext()
и "this
"?
Хотя это простой вопрос, я не могу понять основную разницу между ними. Если возможно, приведите несколько простых примеров.
View.getContext()
: возвращает контекст, в котором в настоящее время выполняется представление. Обычно текущая активная активность.
Activity.getApplicationContext()
: возвращает контекст для всего приложения (процесс, в котором все действия запущены внутри
из). Используйте это вместо текущего контекста активности, если вам нужно
контекст, привязанный к жизненному циклу всего приложения, а не только
текущая деятельность.
ContextWrapper.getBaseContext()
: если вам нужен доступ к контексту из другого контекста, вы используете ContextWrapper.
Контекст, на который ссылается внутри, что ContextWrapper доступен через
getBaseContext().
Большинство ответов уже охватывают getContext()
и getApplicationContext()
, но getBaseContext() редко объясняется.
Метод getBaseContext()
применим только тогда, когда у вас есть ContextWrapper
.
Android предоставляет класс ContextWrapper
, созданный вокруг существующего Context
, используя:
ContextWrapper wrapper = new ContextWrapper(context);
Преимущество использования ContextWrapper
заключается в том, что он позволяет вам "изменять поведение без изменения исходного контекста". Например, если у вас есть действие под названием myActivity
, то можно создать View
с другой темой, чем myActivity
:
ContextWrapper customTheme = new ContextWrapper(myActivity) {
@Override
public Resources.Theme getTheme() {
return someTheme;
}
}
View myView = new MyView(customTheme);
ContextWrapper
действительно эффективен, потому что он позволяет вам отменить большинство функций, предоставляемых Context
, включая код для доступа к ресурсам (например, openFileInput()
, getString()
), взаимодействовать с другими компонентами (например, sendBroadcast()
, registerReceiver()
), запрашивает разрешения (например, checkCallingOrSelfPermission()
) и разрешает расположение файловой системы (например, getFilesDir()
). ContextWrapper
действительно полезен для решения проблем с конкретными устройствами/версиями или для применения одноразовых настроек к компонентам, таким как представления, требующие контекста.
Метод getBaseContext() может использоваться для доступа к "базовому" контексту, который обтекает ContextWrapper
. Вам может потребоваться доступ к "базовому" контексту, если вам нужно, например, проверить, есть ли его Service
, Activity
или Application
:
public class CustomToast {
public void makeText(Context context, int resId, int duration) {
while (context instanceof ContextWrapper) {
context = context.baseContext();
}
if (context instanceof Service)) {
throw new RuntimeException("Cannot call this from a service");
}
...
}
}
Или, если вам нужно вызвать "развернутую" версию метода:
class MyCustomWrapper extends ContextWrapper {
@Override
public Drawable getWallpaper() {
if (BuildInfo.DEBUG) {
return mDebugBackground;
} else {
return getBaseContext().getWallpaper();
}
}
}
getApplicationContext(). Возвращает контекст для всех действий, выполняемых в приложении.
getBaseContext(). Если вы хотите получить доступ к Контексту из другого контекста в приложении, к которому вы можете получить доступ.
getContext() - возвращает контекстное представление только текущей текущей активности.
Context
предоставляет информацию о Actvity
или Application
для вновь созданных компонентов.
Соответствующий Context
должен быть предоставлен вновь созданным компонентам (контекст приложения или контекст активности)
Так как Activity
является подклассом Context
, можно использовать this
для получения этого контекста активности
Вопрос "что такое контекст" является одним из самых сложных вопросов во вселенной Android.
Контекст определяет методы, которые обращаются к системным ресурсам, извлекают статические активы приложения, проверяют разрешения, выполняют манипуляции с пользовательским интерфейсом и многое другое. По сути, Context
является примером анти-паттерна God Object в производстве.
Когда речь заходит о том, какой тип Context
следует использовать, это становится очень сложным, поскольку, за исключением того, что он является объектом Бога, дерево иерархии подклассов Context
жестоко нарушает принцип подстановки Лискова.
В этом блоге делается попытка обобщить применимость классов Context
в различных ситуациях.
Позвольте мне скопировать основную таблицу из этого поста для полноты:
+----------------------------+-------------+----------+---------+-----------------+-------------------+ | | Application | Activity | Service | ContentProvider | BroadcastReceiver | +----------------------------+-------------+----------+---------+-----------------+-------------------+ | Show a Dialog | NO | YES | NO | NO | NO | | Start an Activity | NO¹ | YES | NO¹ | NO¹ | NO¹ | | Layout Inflation | NO² | YES | NO² | NO² | NO² | | Start a Service | YES | YES | YES | YES | YES | | Bind to a Service | YES | YES | YES | YES | NO | | Send a Broadcast | YES | YES | YES | YES | YES | | Register BroadcastReceiver | YES | YES | YES | YES | NO³ | | Load Resource Values | YES | YES | YES | YES | YES | +----------------------------+-------------+----------+---------+-----------------+-------------------+
- Приложение МОЖЕТ запустить Отсюда Действие, но оно требует создания новой задачи. Это может соответствовать конкретным случаям использования, но может привести к нестандартному поведению бэк-стека в вашем приложении и, как правило, не рекомендуется или считается хорошей практикой.
- Это законно, но инфляция будет выполняться с темой по умолчанию для системы, в которой вы работаете, а не с тем, что определено в вашем приложении.
- Разрешено, если получатель имеет нулевое значение, которое используется для получения текущего значения липкой трансляции, на Android 4.2 и выше.
Часть UML-диаграммы контекста
Контекст обеспечивает общую реализацию для доступа к уровню приложения, а также к ресурсам системного уровня.
Контекст приложения. Это экземпляр-одиночка, привязанный к жизненному циклу приложения.
Контекст действия - доступен в действии. Этот контекст связан с жизненным циклом действия. Контекст действия следует использовать, когда вы передаете контекст в области действия или вам нужен контекст, жизненный цикл которого привязан к текущему контексту.
getBaseContext() - эффективно возвращает то, какой контекст оборачивается ContextWrapper. Глядя на код, я могу сказать, что это, скорее всего, действие или приложение, однако у ContextWrapper более 40 известных прямых и косвенных дочерних элементов.
getContext() в ContentProvider - этот контекст является контекстом приложения и может использоваться аналогично контексту приложения.
Из этого docs
Я понял, что вы должны использовать:
Попробуйте использовать контекстное приложение вместо контекстной активности
getApplicationContext()
это используется для уровня приложения и относится ко всем действиям.
getContext() и getBaseContext()
скорее всего, один и тот же. В этом выражается только текущая активность, которая является живой.
это
всегда ссылается на текущий объект класса.