Kiedy wywołać kontekst aktywności lub kontekst aplikacji?

Pojawiło się wiele postów na temat tego, czym są te dwa konteksty.. Ale i tak nie rozumiem tego całkiem dobrze

As I understand it so far: Każda z nich jest instancją swojej klasy, co oznacza, że niektórzy programiści zalecają używanie this.getApplicationContext() tak często, jak to możliwe, aby nie "wyciekać" z pamięci. Dzieje się tak dlatego, że drugi this (uzyskanie kontekstu instancji Activity) wskazuje na Activity, który jest niszczony za każdym razem, gdy użytkownik przechyla telefon lub opuszcza aplikację itp.. Które najwyraźniej Garbage Collector (GC) nie łapie i dlatego zużywa zbyt dużo pamięci..

Ale czy ktoś może wymyślić kilka naprawdę dobrych przykładów kodowania, gdzie byłoby właściwe użycie this (uzyskanie kontekstu bieżącej instancji Activity) i kontekst aplikacji będzie bezużyteczny / zły?

Author: Brian Tompsett - 汤莱恩, 2011-09-04

7 answers

getApplicationContext() prawie zawsze się myli. Pani Hackborn (m.in.) była bardzo wyraźna, że używasz tylko wtedy, gdy wiesz dlaczego używasz i tylko wtedy, gdy potrzebujesz aby używać getApplicationContext().

Mówiąc wprost, "niektórzy programiści" używają getApplicationContext() (lub getBaseContext(), w mniejszym stopniu), ponieważ ich doświadczenie w Javie jest ograniczone. Implementują klasę wewnętrzną (np. an OnClickListener dla a Button W an Activity) i potrzebują a Context. Zamiast używać MyActivity.this, aby uzyskać Na Zewnątrz Klasa " this, używają getApplicationContext() lub getBaseContext(), aby uzyskać obiekt Context.

Ty tylko używaj getApplicationContext()kiedy wiesz potrzebujesz Context do czegoś, co może żyć dłużej niż jakiekolwiek inne prawdopodobne Context masz do dyspozycji. Scenariusze obejmują:

  • Użyj getApplicationContext(), jeśli potrzebujesz czegoś związanego z Context, które samo w sobie będzie miało zasięg globalny. Używam getApplicationContext(), Na przykład, w WakefulIntentService, aby statyczny WakeLock był używany dla usługi. Ponieważ to WakeLock jest statyczne, a ja potrzebuję Context aby uzyskać PowerManager aby go utworzyć, najbezpieczniej jest użyć getApplicationContext().

  • Jeśli chcesz przekazać ServiceConnection (tj. uchwyt do wiązania) pomiędzy instancjami Activity poprzez onRetainNonConfigurationInstance(), użyj getApplicationContext(), gdy połączysz się z Service Z Activity. Android wewnętrznie śledzi wiązania za pomocą tych ServiceConnections i przechowuje odniesienia do Contexts, które tworzą wiązania. Jeśli bindujesz z Activity, wtedy nowa instancja Activity będzie miała odniesienie do ServiceConnection, które ma ukryte odniesienie do starego Activity, oraz stare Activity nie mogą być zbierane śmieci.

Niektórzy programiści używają niestandardowych podklas Application dla własnych danych globalnych, które pobierają za pośrednictwem getApplicationContext(). To z pewnością możliwe. Preferuję statyczne elementy danych, jeśli nie z innego powodu niż ty możesz mieć tylko jeden Niestandardowy Application obiekt. Zbudowałem jedną aplikację przy użyciu niestandardowego obiektu Application i uznałem, że jest to bolesne. Pani Hackborn również zgadza się z tym stanowiskiem.

Oto powody, dla których Nie do użyj getApplicationContext() gdziekolwiek jesteś:

  • Nie jest kompletnym Context, wspierającym wszystko, co robi Activity. Różne rzeczy, które spróbujesz zrobić z tym Context, zawiodą, głównie związane z GUI .

  • Może tworzyć wycieki pamięci, jeśli Context z getApplicationContext() trzyma coś stworzonego przez twoje wywołania na nim, którego nie wyczyścisz. Z Activity, jeśli trzyma się czegoś, gdy Activity zostanie zebrany śmieci, Wszystko inne też się wypłukuje. Application obiekt pozostaje przez cały okres trwania procesu.

 375
Author: CommonsWare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:50

Myślę, że jest wiele rzeczy, które są słabo udokumentowane na stronie SDK, to jeden z nich. Twierdzenie, które zamierzam złożyć, jest takie, że wydaje się, że lepiej jest domyślnie używać kontekstu aplikacji i używać kontekstu aktywności tylko wtedy, gdy naprawdę trzeba. Jedyne miejsce, w którym kiedykolwiek widziałem, że potrzebujesz kontekstu aktywności, to okno postępu. Sberg412 twierdzi, że musisz użyć kontekstu aktywności do wiadomości toast, ale dokumenty Androida wyraźnie pokazują aplikację używany kontekst. Zawsze używałem kontekstu aplikacji do toastów z powodu tego przykładu Google. Jeśli jest to złe, to Google upuścił piłkę tutaj.

Tutaj jest więcej do przemyślenia i recenzji:

Dla wiadomości toast, Przewodnik Google Dev używa kontekstu aplikacji i wyraźnie mówi, aby go używać: Powiadomienia Tostów

W sekcji dialogów przewodnika deweloperów zobaczysz, że AlertDialog.Builder używa kontekstu aplikacji, a następnie paska postępu używa kontekstu aktywności. To nie jest wyjaśnione przez Google. dialogi

Wydaje się, że dobrym powodem do używania kontekstu aplikacji jest to, że chcesz obsługiwać zmiany konfiguracji, takie jak zmiana orientacji, i chcesz zachować obiekty, które wymagają kontekstu, takiego jak widoki. Jeśli zajrzysz tutaj: zmiany czasu wykonywania Należy zachować ostrożność przy użyciu kontekstu aktywności, który może spowodować wyciek. Można tego uniknąć za pomocą kontekstu aplikacji z widokami, które mają być zachowane (w przynajmniej tak Rozumiem). W aplikacji, którą piszę, zamierzam użyć kontekstu aplikacji, ponieważ staram się trzymać niektóre widoki i inne rzeczy na zmianę orientacji, i nadal chcę, aby aktywność została zniszczona i odtworzona na zmiany orientacji. Dlatego muszę użyć kontekstu aplikacji, aby nie spowodować wycieku pamięci(zobacz unikanie wycieków pamięci ). Wydaje mi się, że istnieje wiele dobrych powodów, aby używać kontekstu aplikacji zamiast kontekstu aktywności, a dla mnie prawie wygląda na to, że używasz go częściej niż kontekstu aktywności. Tak robi wiele książek na Androida, przez które przeszedłem, i tak robi wiele przykładów Google, które widziałem.

Dokumentacja Google naprawdę sprawia, że korzystanie z kontekstu aplikacji jest w większości przypadków w porządku, a w rzeczywistości pojawia się częściej niż używanie kontekstu aktywności w ich przykładach (przynajmniej przykłady widziałem). Jeśli to naprawdę taki problem używać kontekstu aplikacji, to Google naprawdę należy położyć na tym większy nacisk. Muszą to wyjaśnić i muszą powtórzyć niektóre ze swoich przykładów. Nie winię tego całkowicie na niedoświadczonych programistów, ponieważ autorytet (Google) naprawdę sprawia, że wygląda to tak, jakby nie było problemu z użyciem kontekstów aplikacji.

 46
Author: Andi Jay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-15 05:19:30

Użyłem tej tabeli jako wskazówki, kiedy używać różnych typów kontekstu, takich jak kontekst aplikacji (TJ: getApplicationContext()) i kontekst aktywności , również kontekst BroadcastReceiver :

Tutaj wpisz opis obrazka

Oryginalny artykuł tutaj aby uzyskać więcej informacji.

 29
Author: commonSenseCode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-18 08:46:33

Jakiego kontekstu użyć?

Istnieją dwa rodzaje kontekstu:

  1. Kontekst aplikacji jest związany z aplikacją i zawsze będzie taki sam przez cały okres jej użytkowania-nie zmienia się. Więc jeśli używasz Toast, możesz użyć kontekstu aplikacji lub nawet kontekstu aktywności (obu), ponieważ toast może być wyświetlany z dowolnego miejsca w aplikacji i nie jest dołączony do określonego okna. Ale jest wiele wyjątków, jeden wyjątkiem jest sytuacja, gdy trzeba użyć lub przekazać kontekst aktywności.

  2. Kontekst aktywności jest powiązany z działaniem i może zostać zniszczony, jeśli działanie zostanie zniszczone-może być wiele działań (więcej niż prawdopodobne) z jedną aplikacją. A czasami absolutnie potrzebujesz obsługi kontekstu aktywności. Na przykład, jeśli uruchomisz nową aktywność, musisz użyć kontekstu aktywności w jego intencji, aby nowa aktywność była połączona z aktualna aktywność pod względem stosu aktywności. Możesz jednak użyć kontekstu aplikacji do uruchomienia nowej aktywności, ale następnie musisz ustawić flagę Intent.FLAG_ACTIVITY_NEW_TASK w celu potraktowania jej jako nowego zadania.

Rozważmy kilka przypadków:

  • MainActivity.this odnosi się do głównego kontekstu Activity, który rozszerza klasę Activity, ale klasa bazowa (activity) również rozszerza klasę Context, więc może być używana do oferowania kontekstu activity.

  • getBaseContext() oferta działalności kontekst.

  • getApplication() oferuje kontekst aplikacji.

  • getApplicationContext() oferuje również kontekst aplikacji.

Aby uzyskać więcej informacji, sprawdź ten link .

 10
Author: Zohra Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-07 19:10:21

Dwa świetne przykłady tego, kiedy należy użyć kontekstu aktywności w porównaniu z kontekstem aplikacji, to wyświetlenie komunikatu Toast lub wbudowanego komunikatu dialogowego, ponieważ użycie kontekstu aplikacji spowoduje wyjątek:

ProgressDialog.show(this, ....);

Lub

Toast t = Toast.makeText(this,....);

Oba te elementy wymagają informacji z kontekstu aktywności, który nie jest podany w kontekście aplikacji.

 3
Author: SBerg413,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-04 11:38:57

kontekst aplikacji żyć dopóki aplikacja jest żywa tylko i to nie zależy od cyklu życia aktywności, ale, kontekst zachować obiekt długotrwały . Jeśli obiekt, który jest używany jako tymczasowy, to time use Application Contexti Activity Context jest używany całkowicie w kontekście aplikacji.

 3
Author: Ganesh Katikar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-06 13:23:37

Zastanawiałem się, dlaczego nie użyć kontekstu aplikacji dla każdej operacji, którą obsługuje. W końcu zmniejsza to ryzyko wycieku pamięci i braku sprawdzenia null dla getContext () lub getActivity () (przy użyciu iniekcyjnego kontekstu aplikacji lub pozyskanego metodą statyczną z aplikacji). Wypowiedzi, takie jak ta autorstwa Pani Hackborn, która używała kontekstu aplikacji tylko w razie potrzeby, nie wydają mi się przekonujące bez wyjaśnienia dlaczego. / Align = "left" / dlaczego:

Odkryli, że istnieją problemy w niektórych kombinacjach wersji Androida / urządzeń, które nie przestrzegają tych zasad. Na przykład, jeśli mam BroadcastReceiver, który jest przekazywany przez kontekst i konwertuję ten kontekst do kontekstu aplikacji, a następnie próbuję wywołać registerReceiver () w kontekście aplikacji, istnieje wiele przypadków, w których działa to dobrze, ale także wiele przypadków, w których dostaję awarię z powodu ReceiverCallNotAllowedException. Awarie te występują w szerokim zakresie wersji Androida od API 15 do 22. https://possiblemobile.com/2013/06/context/#comment-2443283153

Ponieważ nie jest gwarantowane, że wszystkie operacje opisane jako obsługiwane przez kontekst aplikacji w poniższej tabeli będą działać na wszystkich urządzeniach z Androidem! Tutaj wpisz opis obrazka

 3
Author: Malachiasz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:07