Różnica między getContext (), getApplicationContext (), getBaseContext () i „this”

565

Jaka jest różnica między getContext(), getApplicationContext(), getBaseContext(), i " this„?

Chociaż jest to proste pytanie, nie jestem w stanie zrozumieć podstawowej różnicy między nimi. Proszę podać kilka prostych przykładów, jeśli to możliwe.

iCurious
źródło
1
W pierwszej odpowiedzi jest doskonały opis: stackoverflow.com/questions/1026973/…
ky1enamic

Odpowiedzi:

528
  • View.getContext(): Zwraca kontekst, w którym widok jest obecnie uruchomiony. Zwykle aktywna aktywność.

  • Activity.getApplicationContext(): Zwraca kontekst dla całej aplikacji (proces, w którym działają wszystkie działania). Użyj tego zamiast bieżącego kontekstu działania, jeśli potrzebujesz kontekstu związanego z cyklem życia całej aplikacji, a nie tylko bieżącego działania.

  • ContextWrapper.getBaseContext(): Jeśli potrzebujesz dostępu do kontekstu z innego kontekstu, użyj ContextWrapper. Dostęp do kontekstu, do którego odwołuje się ten ContextWrapper, jest uzyskiwany za pośrednictwem getBaseContext ().

Alexander Lucas
źródło
59
a co z „tym”?
CooL i3oY
16
+ CooL i3oY to samo z getContext
Mikey,
13
w rzeczywistości jestem zdezorientowany, co to jest właściwe określenie kontekstu?
Ravi
11
„this” i getContext () oba są takie same
KCRaju 24.08.13
43
thisi getContext()nie zawsze są takie same, np. w klasie Activity, możesz użyć, thisponieważ Activitydziedziczy, Contextale metoda getContext()nie jest w Activityklasie. @mikedroid @KCRaju
nandan
92

Większość odpowiedzi już pokryć getContext()i getApplicationContext()ale getBaseContext () jest rzadko wyjaśnione.

Ta metoda getBaseContext()jest ważna tylko wtedy, gdy masz ContextWrapper. Android zapewnia ContextWrapperklasę utworzoną wokół istniejącej Contextza pomocą:

ContextWrapper wrapper = new ContextWrapper(context);

Zaletą używania a ContextWrapperjest to, że pozwala „modyfikować zachowanie bez zmiany oryginalnego kontekstu”. Na przykład, jeśli masz aktywność o nazwie, myActivitymożesz utworzyć Viewz innym motywem niż myActivity:

ContextWrapper customTheme = new ContextWrapper(myActivity) {
  @Override
  public Resources.Theme getTheme() { 
    return someTheme;
  }
}
View myView = new MyView(customTheme);

ContextWrapperjest naprawdę potężny, ponieważ pozwala zastąpić większość funkcji oferowanych przez Contexttym kod dostępu do zasobów (np openFileInput(), getString()), interakcje z innymi składnikami (np sendBroadcast(), registerReceiver()), żądania uprawnienia (np checkCallingOrSelfPermission()) i lokalizacje rozwiązywania systemie plików (np getFilesDir()). ContextWrapperjest naprawdę przydatny do obejścia problemów specyficznych dla urządzenia / wersji lub zastosowania jednorazowych dostosowań do komponentów takich jak Widoki, które wymagają kontekstu.

Metodę getBaseContext () można wykorzystać do uzyskania dostępu do „podstawowego” kontekstu, który jest ContextWrapperzawijany. Konieczne może być uzyskanie dostępu do kontekstu „podstawowego”, jeśli chcesz na przykład sprawdzić, czy jest to Service, Activityczy 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");
    }
    ...
  }
}

Lub jeśli chcesz wywołać „nieopakowaną” wersję metody:

class MyCustomWrapper extends ContextWrapper {
  @Override
  public Drawable getWallpaper() {
    if (BuildInfo.DEBUG) {
      return mDebugBackground;
    } else {
      return getBaseContext().getWallpaper();
    }
  }
}
Mike Laren
źródło
17
Powiedziałbym, że jest to najważniejsza odpowiedź po zaakceptowanej.
0leg
4
Powiedziałbym, że istnienie ContextWrapperjest jedną z najgorszych decyzji, jakie kiedykolwiek podjęli twórcy frameworka Android. Kiedy zdali sobie sprawę, że stworzyli całą rodzinę Boskich Przedmiotów, zamiast zrobić właściwą rzecz i zmienić kod na Pojedynczą Odpowiedzialność, dodali brzydkiego hacka, który pozwolił zmienić zachowanie Kontekstu poprzez pogłębienie drzewa dziedziczenia. Zła inżynieria oprogramowania w najbrzydszym stanie. Jeśli chodzi o nas, programistów, IMHO nikt nigdy nie powinien używać getBaseContext()ani ContextWrapper. Jeśli tak, to ogromny zapach kodu.
Wasilij
Chciałbym zobaczyć cały CustomToastkod. ) :)))
Alston
39

getApplicationContext () - Zwraca kontekst dla wszystkich działań uruchomionych w aplikacji.

getBaseContext () - Jeśli chcesz uzyskać dostęp do kontekstu z innego kontekstu w aplikacji, do której masz dostęp.

getContext () - Zwraca widok kontekstowy tylko bieżącą działającą aktywność.

Jay Patel
źródło
1
Pls włączają literę A i B do swojej definicji kontekstu w kontekście, w żadnej odpowiedzi nie jest jasne, który kontekst jest dostępny.
Mam nadzieję, że będzie
29

Pytanie „czym jest kontekst” jest jednym z najtrudniejszych pytań we wszechświecie Androida.

Kontekst definiuje metody dostępu do zasobów systemowych, pobierania statycznych zasobów aplikacji, sprawdzania uprawnień, wykonywania operacji interfejsu użytkownika i wielu innych. Zasadniczo Contextjest przykładem anty-wzoru God Object w produkcji.

Jeśli chodzi o to, jakiego rodzaju Contextpowinniśmy użyć, staje się bardzo skomplikowane, ponieważ z wyjątkiem bycia Bogiem Obiektem drzewo hierarchii Contextpodklas brutalnie narusza Zasadę podstawienia Liskowa.

Ten post na blogu próbuje podsumować Contextzastosowanie klas w różnych sytuacjach.

Pozwól mi skopiować główną tabelę z tego postu dla kompletności:

+----------------------------+-------------+----------+---------+-----------------+-------------------+
|                            | 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. Aplikacja MOŻE rozpocząć działanie od tego miejsca, ale wymaga utworzenia nowego zadania. Może to pasować do konkretnych przypadków użycia, ale może tworzyć niestandardowe zachowania stosu wstecznego w aplikacji i na ogół nie jest zalecane ani uważane za dobrą praktykę.
  2. Jest to legalne, ale inflacja zostanie wykonana przy użyciu domyślnego motywu dla systemu, na którym działasz, a nie tego, co jest zdefiniowane w twojej aplikacji.
  3. Dozwolone, jeśli odbiornik ma wartość zerową, co służy do uzyskiwania bieżącej wartości lepkiej transmisji na Androidzie 4.2 i nowszych.

zrzut ekranu

Wasilij
źródło
Świetny post na blogu, do którego linkujesz!
lejonl
28

Contextdostarcza informacji o Actvitylub Applicationdo nowo utworzonych elementów.

Odpowiednie informacje Contextnależy podać w nowo utworzonych komponentach (niezależnie od tego, czy kontekst aplikacji czy kontekst działania)

Ponieważ Activityjest to podklasa Context, można użyć thisdo uzyskania kontekstu tego działania

tez
źródło
Gdzie jest twoje wyjaśnienie dotyczące baseContext?
IgorGanapolsky
1

Z tego dokumentu

Zrozumiałem, że powinieneś użyć:

Spróbuj użyć aplikacji kontekstowej zamiast działania kontekstowego

mehmet
źródło
0

getApplicationContext ()

służy to do poziomu aplikacji i odnosi się do wszystkich działań.

getContext () i getBaseContext ()

jest najprawdopodobniej taki sam. dotyczy to tylko bieżącej aktywności, która jest na żywo.

to

zawsze odnosi się do bieżącego obiektu klasy.

Jatin Bansal
źródło
0

A Contextto:

  • klasa abstrakcyjna, której implementację zapewnia system Android.
  • Umożliwia dostęp do zasobów i klas specyficznych dla aplikacji, a także wezwań do wykonywania operacji na poziomie aplikacji, takich jak uruchamianie działań, nadawanie i odbieranie zamiarów itp.
SANKET RAMANI
źródło