getApplicationContext()
prawie zawsze się myli. Pani Hackborn (między innymi) były bardzo wyraźne, że tylko używać getApplicationContext()
, gdy wiesz, dlaczego używasz getApplicationContext()
i tylko wtedy, gdy trzeba użyć getApplicationContext()
.
Mówiąc wprost, „niektórzy programiści” używają getApplicationContext()
(lub getBaseContext()
, w mniejszym stopniu), ponieważ ich doświadczenie z Javą jest ograniczone. Wypełniają wewnętrzną klasy (np An OnClickListener
dla Button
w sposób Activity
) i potrzebują Context
. Zamiast MyActivity.this
uzyskiwać dostęp do klasy zewnętrznej this
, używają getApplicationContext()
lub getBaseContext()
uzyskują Context
obiekt.
Ty tylko używać getApplicationContext()
kiedy wiedzą Państwo potrzebują Context
czegoś, które mogą żyć dłużej niż jakakolwiek inna prawdopodobnie Context
masz do dyspozycji. Scenariusze obejmują:
Użyj, getApplicationContext()
jeśli potrzebujesz czegoś powiązanego z czymś, Context
co samo będzie miało zasięg globalny. Używam getApplicationContext()
, na przykład, w WakefulIntentService
, do statycznego, WakeLock
który ma być używany dla usługi. Ponieważ WakeLock
jest to statyczne i muszę się Context
do niego dostać PowerManager
, najbezpieczniej jest go używać getApplicationContext()
.
Użyj, getApplicationContext()
gdy łączysz się Service
z z Activity
, jeśli chcesz przekazać ServiceConnection
(tj. Uchwyt do wiązania) między Activity
instancjami przez onRetainNonConfigurationInstance()
. Android wewnętrznie śledzi powiązania za ich pośrednictwem ServiceConnections
i przechowuje odniesienia do tych, Contexts
które tworzą powiązania. Jeśli utworzysz powiązanie z Activity
, nowe Activity
wystąpienie będzie zawierało odwołanie do tego, ServiceConnection
które ma niejawne odniesienie do starego Activity
, a starego Activity
nie można wyrzucać.
Niektórzy programiści używają niestandardowych podklas Application
własnych danych globalnych, które pobierają getApplicationContext()
. To z pewnością możliwe. Wolę statyczne elementy danych, jeśli tylko z jednego powodu możesz mieć tylko jedenApplication
obiekt niestandardowy . Zbudowałem jedną aplikację za pomocą niestandardowego Application
obiektu i okazało się to bolesne. Pani Hackborn zgadza się również z tym stanowiskiem .
Oto powody, dla których niegetApplicationContext()
możesz używać gdziekolwiek jesteś:
To nie jest kompletne Context
, obsługujące wszystko, co Activity
robi. Różne rzeczy, które spróbujesz z tym zrobić Context
, zawiodą, głównie związane z GUI .
Może powodować wycieki pamięci, jeśli „ Context
from” getApplicationContext()
zatrzymuje coś utworzonego przez wywołania, których nie usuwasz. Z Activity
, jeśli coś się trzyma, kiedy Activity
śmieci zostaną zebrane, wszystko inne również się wypłukuje. Application
Obiekt pozostaje przez cały okres procesu.
getApplicationContext()
wtedy, gdy dokładnie wiesz , dlaczego potrzebujesz go w danej sytuacji. Nadmuchujesz układ? Skorzystaj z aktywności. Powiązanie z usługą, gdzie potrzebujesz tego powiązania, aby przetrwać zmianę konfiguracji? UżyjgetApplicationContext()
, aby powiązanie nie było powiązane zActivity
instancją.Myślę, że na stronie SDK jest wiele słabo udokumentowanych rzeczy, to jedna z nich. Twierdzę, że zamierzam powiedzieć, że wydaje się, że lepiej jest domyślnie używać kontekstu aplikacji i używać kontekstu aktywności tylko wtedy, gdy naprawdę tego potrzebujesz. Jedynym miejscem, w którym kiedykolwiek widziałem, że potrzebujesz kontekstu aktywności, jest okno dialogowe postępu. SBERG412 twierdzi, że musisz użyć kontekstu działania dla wiadomości toast, ale dokumenty systemu Android wyraźnie pokazują używany kontekst aplikacji. Z tego przykładu Google zawsze korzystałem z kontekstu aplikacji dla tostów. Jeśli to źle, Google upuścił piłkę tutaj.
Oto więcej do przemyślenia i przeglądu:
W przypadku wiadomości Toast Przewodnik Google Dev korzysta z kontekstu aplikacji i wyraźnie mówi, aby go użyć: Powiadomienia o Toast
W sekcji okien dialogowych przewodnika dla programistów widać, że AlertDialog.Builder używa kontekstu aplikacji, a następnie pasek postępu używa kontekstu aktywności. To nie jest wyjaśnione przez Google. Dialogi
Wydaje się, że dobrym powodem do korzystania z kontekstu aplikacji jest to, że chcesz obsługiwać zmiany konfiguracji, takie jak zmiana orientacji, i chcesz zachować obiekty, które potrzebują kontekstu, takiego jak Widoki. Jeśli spojrzysz tutaj: Zmiany w czasie wykonywania Zachowaj ostrożność podczas używania kontekstu aktywności, który może spowodować wyciek. Można tego uniknąć dzięki kontekstowi aplikacji z widokami, które należy zachować (przynajmniej tak rozumiem). W aplikacji, którą piszę, zamierzam użyć kontekstu aplikacji, ponieważ próbuję zachować pewne widoki i inne rzeczy przy zmianie orientacji, a nadal chcę, aby aktywność została zniszczona i odtworzona po zmianie orientacji. Dlatego muszę użyć kontekstu aplikacji, aby nie spowodować wycieku pamięci (patrz Unikanie wycieków pamięci). Wydaje mi się, że istnieje wiele dobrych powodów, aby używać kontekstu aplikacji zamiast kontekstu działania, a dla mnie prawie wydaje się, że używałbyś go częściej niż kontekstu działania. Tak właśnie wydaje się robić wiele książek o Androidzie i tak właśnie wygląda większość przykładów Google.
Dokumentacja Google naprawdę wydaje się, że korzystanie z kontekstu aplikacji jest w większości przypadków w porządku i faktycznie pojawia się częściej niż użycie kontekstu aktywności w ich przykładach (przynajmniej w przykładach, które widziałem). Jeśli korzystanie z kontekstu aplikacji jest naprawdę takim problemem, Google naprawdę musi położyć na to większy nacisk. Muszą to wyjaśnić i muszą powtórzyć niektóre ze swoich przykładów. Nie winiłbym tego całkowicie za niedoświadczonych programistów, ponieważ władza (Google) naprawdę sprawia, że wygląda na to, że korzystanie z kontekstów aplikacji nie stanowi problemu.
źródło
Wykorzystałem tę tabelę jako wskazówkę, kiedy używać różnych typów kontekstu, takich jak kontekst aplikacji (tj .:)
getApplicationContext()
i kontekst aktywności , a także kontekst BroadcastReceiver :Wszystkie zasługi należą do oryginalnego autora tutaj, aby uzyskać więcej informacji.
źródło
Istnieją dwa rodzaje kontekstu:
Kontekst aplikacji jest powiązany z aplikacją i zawsze będzie taki sam przez cały okres użytkowania aplikacji - nie zmienia się. Jeśli więc używasz Toast, możesz użyć kontekstu aplikacji, a nawet kontekstu aktywności (oba), ponieważ toast może być wyświetlany z dowolnego miejsca w aplikacji i nie jest dołączony do konkretnego okna. Istnieje jednak wiele wyjątków, jeden wyjątek dotyczy sytuacji, gdy trzeba użyć lub przekazać kontekst działania.
Kontekst działania jest powiązany z działaniem i może zostać zniszczony, jeśli działanie zostanie zniszczone - może istnieć wiele działań (więcej niż prawdopodobne) w jednej aplikacji. A czasem absolutnie potrzebujesz uchwytu kontekstu aktywności. Na przykład, jeśli uruchomisz nowe działanie, musisz użyć kontekstu działania w jego zamiarze, aby nowe działanie uruchamiające było połączone z bieżącym działaniem pod względem stosu działań. Możesz jednak użyć kontekstu aplikacji, aby uruchomić nową aktywność, ale musisz ustawić flagę,
Intent.FLAG_ACTIVITY_NEW_TASK
aby traktować ją jako nowe zadanie.Rozważmy kilka przypadków:
MainActivity.this
odnosi się do kontekstu MainActivity, który rozszerza klasę Activity, ale klasa podstawowa (działanie) również rozszerza klasę Context, więc można jej użyć do zaoferowania kontekstu działania.getBaseContext()
oferuje kontekst działania.getApplication()
oferuje kontekst aplikacji.getApplicationContext()
oferuje również kontekst aplikacji.Aby uzyskać więcej informacji, sprawdź ten link .
źródło
downloadmanager
, a gdy odbierany jest gotowy sygnał, powinien wyświetlić okno dialogowe np. „Co chcesz zrobić z tym pobieraniem?”. Moje rozwiązanie (hack) zapisuje najnowszeActivity
wstatic
Application
klasie i żąda bieżącegoActivity
po zakończeniu pobierania. Wątpię jednak, aby była to właściwa implementacja. TL; DR Jak wyświetlić AlertDialog w dowolnym miejscu w aplikacji?Zastanawiałem się, dlaczego nie używać kontekstu aplikacji dla każdej obsługiwanej operacji. W końcu zmniejsza ryzyko wycieku pamięci i braku kontroli zerowej dla getContext () lub getActivity () (podczas korzystania z wstrzykniętego kontekstu aplikacji lub uzyskanego metodą statyczną z aplikacji). Stwierdzenia, takie jak te pani Hackborn, by używać kontekstu aplikacji tylko w razie potrzeby, nie wydają mi się przekonujące bez wyjaśnienia, dlaczego. Wygląda jednak na to, że znalazłem nieznane, dlaczego:
Ponieważ nie ma gwarancji, że wszystkie operacje opisane jako obsługiwane przez kontekst aplikacji w poniższej tabeli będą działać na wszystkich urządzeniach z Androidem!
źródło
Dwa świetne przykłady użycia kontekstu działania a kontekstu aplikacji to wyświetlanie komunikatu Toast lub wbudowanego okna dialogowego, ponieważ użycie kontekstu aplikacji spowoduje wyjątek:
lub
Oba wymagają informacji z kontekstu działania, które nie są podane w kontekście aplikacji.
źródło
Kontekst aplikacji na żywo aż aplikacja żyje tylko i to nie zależy od aktywności życiowej Cyklu ale kontekstowego keep obiektu długowieczne . Jeśli obiekt, z którego korzystasz tymczasowo, korzysta z kontekstu aplikacji i kontekstu działania jest całkowicie przeciwny do kontekstu aplikacji.
źródło