Разница между getContext (), getApplicationContext (), getBaseContext () и «этим»


566

В чем разница между getContext(), getApplicationContext(), getBaseContext()и " this«?

Хотя это простой вопрос, я не могу понять принципиальную разницу между ними. Пожалуйста, приведите несколько простых примеров, если это возможно.


1
В первом ответе есть отличная запись: stackoverflow.com/questions/1026973/…
ky1enamic

Ответы:


529
  • View.getContext()Возвращает контекст, в котором в данный момент выполняется представление. Обычно текущая активная активность.

  • Activity.getApplicationContext()Возвращает контекст для всего приложения (процесс, внутри которого выполняются все действия). Используйте это вместо текущего контекста Activity, если вам нужен контекст, связанный с жизненным циклом всего приложения, а не только с текущим Activity.

  • ContextWrapper.getBaseContext(): Если вам нужен доступ к контексту из другого контекста, вы используете ContextWrapper. Контекст, на который ссылается внутри этого ContextWrapper, доступен через getBaseContext ().


59
а что насчет "этого"?
CooL i3oY

16
+ CooL i3oY то же самое с getContext
Майки

13
на самом деле я запутался, что такое правильное определение контекста ??
Рави

11
«this» и getContext () оба одинаковы
KCRaju

43
thisи getContext()не всегда одинаковы, например, в классе Activity, вы можете использовать, thisпотому что Activityнаследует, Contextно метод getContext()не в Activityклассе. @mikedroid @KCRaju
Нандан

92

Большинство ответов уже охватывают getContext()и getApplicationContext()но getBaseContext () редко объяснено.

Метод getBaseContext()актуален только тогда, когда у вас есть ContextWrapper. Android предоставляет ContextWrapperкласс, который создается с Contextиспользованием существующего :

ContextWrapper wrapper = new ContextWrapper(context);

Преимущество использования a 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();
    }
  }
}

17
Я бы сказал, это самый важный ответ после принятого.
ноября

4
Я бы сказал, что существование ContextWrapper- одно из худших решений, когда-либо принятых разработчиками платформы Android. Когда они поняли, что создали целое семейство Объектов Бога, вместо того, чтобы делать правильные вещи и рефакторинг кода в сторону Единой Ответственности, они добавили уродливый хак, который позволил изменить поведение контекста путем углубления дерева наследования. Плохая программная инженерия в самом уродливом виде. Что касается нас, разработчиков, ИМХО , никто никогда не должен использовать getBaseContext()или ContextWrapper. Если вы делаете - это огромный «кодовый запах».
Василий

Я хотел бы увидеть полный CustomToastкод. ) : ))))))
Алстон

39

getApplicationContext () - возвращает контекст для всех действий, выполняемых в приложении.

getBaseContext () - если вы хотите получить доступ к контексту из другого контекста в приложении, вы можете получить к нему доступ.

getContext () - возвращает контекстное представление только текущей текущей активности.


1
Просьба включить буквы А и В в ваше определение контекста в контексте, при любом ответе неясно, к какому контексту осуществляется доступ.
Надеюсь, что это

30

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

Скриншот


Отличный пост в блоге, на который вы ссылаетесь!
lejonl

28

Contextпредоставляет информацию о ActvityилиApplication только что созданным компонентам.

Соответствующее Contextдолжно быть предоставлено вновь созданным компонентам (будь то контекст приложения или контекст действия)

Так Activityкак это подкласс Context, можно использовать, thisчтобы получить контекст этой деятельности


Где ваше объяснение о baseContext?
Игорь Ганапольский

1

Из этой документации

Я понял, что вы должны использовать:

Попробуйте использовать контекстное приложение вместо контекстной активности


1

getApplicationContext ()

это используется для прикладного уровня и относится ко всем действиям.

getContext () и getBaseContext ()

Это, скорее всего, то же самое. Эти ссылки относятся только к текущей деятельности, которая является живой.

это

всегда ссылается на текущий объект класса.


0

А Contextэто:

  • абстрактный класс, реализация которого обеспечивается системой Android.
  • Он позволяет получить доступ к ресурсам и классам, относящимся к конкретному приложению, а также к дополнительным вызовам для таких операций на уровне приложения, как запуск, широковещание и получение и т. Д.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.