Різниця між getContext (), getApplicationContext (), getBaseContext () та "this"


565

У чому різниця між getContext(), getApplicationContext(), getBaseContext()і " this«?

Хоча це просте запитання, я не можу зрозуміти основну різницю між ними. Надайте, якщо можливо, кілька простих прикладів.


1
Існують різні форми рецензія в першому відповіді: stackoverflow.com/questions/1026973 / ...
ky1enamic

Відповіді:


528
  • View.getContext(): Повертає контекст, в якому переглядається поточний огляд. Зазвичай активна в даний час активність.

  • Activity.getApplicationContext(): Повертає контекст для всієї програми (процес, за яким всі дії виконуються всередині). Використовуйте це замість поточного контексту діяльності, якщо вам потрібен контекст, прив'язаний до життєвого циклу всієї програми, а не лише до поточної діяльності.

  • ContextWrapper.getBaseContext(): Якщо вам потрібен доступ до контексту з іншого контексту, ви використовуєте ContextWrapper. Доступ до контексту, згаданого всередині цього ContextWrapper, здійснюється через getBaseContext ().


59
а що з "цим"?
CooL i3oY

16
+ CooL i3oY те саме з getContext
Майкі

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

11
"це" та getContext () - те саме
KCRaju

43
thisі getContext()не завжди однакові, наприклад, у класі Activity, ви можете використовувати, thisтому що Activityуспадковує від, Contextале метод getContext()не є в Activityкласі. @mikedroid @KCRaju
nandan

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
Я б сказав, це найважливіша відповідь після прийнятої.
0лег

4
Я б сказав, що існування - ContextWrapperце одне з найгірших рішень, яке коли-небудь приймали розробники Android-системи. Коли вони зрозуміли, що вони створили цілу сім'ю об'єктів Бога, замість того, щоб зробити правильну справу і перенаправити код на єдину відповідальність, вони додали некрасивий хак, який дозволив змінити поведінку контексту шляхом поглиблення дерева спадщини. Погана інженерія програмного забезпечення на самому потворному рівні. Щодо нас, розробників, ІМХО ніхто ніколи не повинен використовувати getBaseContext()або ContextWrapper. Якщо ви робите - це величезний «кодовий запах».
Василь

Я хотів би побачити повний CustomToastкод. THANKS :)))
Альстон

39

getApplicationContext () - Повертає контекст для всіх дій, що виконуються в додатку.

getBaseContext () - Якщо ви хочете отримати доступ до Context з іншого контексту в додатку, ви можете отримати доступ.

getContext () - Повертає контекстний вигляд лише поточної запущеної активності.


1
Будь ласка, включіть букви A і B у ваше визначення контексту з цим контекстом, в жодній відповіді не ясно, до якого контексту можна отримати доступ.
СподіваюсьДопомога

29

Питання "що таке контекст" - одне з найскладніших питань у всесвіті Android.

Контекст визначає методи доступу до системних ресурсів, отримання статичних активів програми, перевірки дозволів, виконання маніпуляцій з інтерфейсом та багато іншого. По суті, Contextце приклад протизразка Бога Об'єкта у виробництві.

Коли мова йде про те, який тип 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

З цього док

Я зрозумів, що ви повинні використовувати:

Спробуйте використовувати контекстну програму замість контекстної діяльності


0

getApplicationContext ()

це використовується для рівня програми та стосується всіх заходів.

getContext () та getBaseContext ()

найімовірніше, те саме. цим викладається лише поточна активність, яка живе в прямому ефірі.

це

завжди посилається на об'єкт поточного класу.


0

A Contextце:

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