Разница между getContext(), getApplicationContext(), getBaseContext() и "this"

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

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

Ответы

Ответ 1

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

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

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

Ответ 2

Большинство ответов уже охватывают 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();
    }
  }
}

Ответ 3

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

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

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

Ответ 4

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

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

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

Ответ 5

Вопрос "что такое контекст" является одним из самых сложных вопросов во вселенной 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 и выше.

screenshot

Ответ 6

Часть UML-диаграммы контекста

enter image description here

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

  • Контекст приложения. Это экземпляр-одиночка, привязанный к жизненному циклу приложения.

  • Контекст действия - доступен в действии. Этот контекст связан с жизненным циклом действия. Контекст действия следует использовать, когда вы передаете контекст в области действия или вам нужен контекст, жизненный цикл которого привязан к текущему контексту.

  • getBaseContext() - эффективно возвращает то, какой контекст оборачивается ContextWrapper. Глядя на код, я могу сказать, что это, скорее всего, действие или приложение, однако у ContextWrapper более 40 известных прямых и косвенных дочерних элементов.

  • getContext() в ContentProvider - этот контекст является контекстом приложения и может использоваться аналогично контексту приложения.

Подробнее здесь, здесь

Ответ 7

Из этого docs

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

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

Ответ 8

getApplicationContext()

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

getContext() и getBaseContext()

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

это

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