Czy w aplikacji na Androida jest coś nie tak z następującym podejściem:
public class MyApp extends android.app.Application {
private static MyApp instance;
public MyApp() {
instance = this;
}
public static Context getContext() {
return instance;
}
}
i przekazać go wszędzie (np. SQLiteOpenHelper) tam, gdzie wymagany jest kontekst (i oczywiście nie przecieka)?
android
android-context
Janchenko
źródło
źródło
<application>
węzeł pliku AndroidManifest.xml zawierać następującą definicję atrybutu:android:name="MyApp"
. Moja aplikacja musi znajdować się w tym samym pakiecie, do którego odwołują się twoje manifesty.Odpowiedzi:
Istnieje kilka potencjalnych problemów z tym podejściem, chociaż w wielu okolicznościach (takich jak twój przykład) będzie działać dobrze.
W szczególności powinieneś zachować ostrożność, mając do czynienia ze wszystkim, co dotyczy tego,
GUI
co wymagaContext
. Na przykład, jeśli przekażesz kontekst aplikacji do niegoLayoutInflater
, otrzymasz wyjątek. Ogólnie rzecz biorąc, twoje podejście jest doskonałe: dobrą praktyką jest użycieActivity's
Context
wewnątrz tegoActivity
, aApplication Context
kiedy przekazujesz kontekst poza zakresActivity
aby uniknąć wycieków pamięci .Ponadto, jako alternatywa dla Państwa wzoru można użyć skrótu dzwoniąc
getApplicationContext()
naContext
obiekt (taki jak aktywny), aby uzyskać kontekstu aplikacji.źródło
LayoutInflator
właśnie mi działało. Musiał zostać zmieniony w ciągu ostatnich trzech lat.Z mojego doświadczenia wynika, że takie podejście nie powinno być konieczne. Jeśli potrzebujesz kontekstu do czegokolwiek, zwykle możesz go uzyskać przez wywołanie View.getContext () i używając
Context
uzyskanego tam możesz wywołać Context.getApplicationContext (), aby uzyskaćApplication
kontekst. Jeśli próbujesz uzyskaćApplication
kontekst z tegoActivity
, zawsze możesz wywołać Activity.getApplication (), które powinno być możliwe do przekazania jakoContext
potrzebne do wywołaniaSQLiteOpenHelper()
.Ogólnie rzecz biorąc, wydaje się, że nie ma problemu z twoim podejściem do tej sytuacji, ale radząc sobie z
Context
tym, upewnij się, że nigdzie nie tracisz pamięci, jak opisano na oficjalnym blogu Google Android Developers .źródło
Niektórzy pytają: jak singleton może zwrócić wskaźnik zerowy? Odpowiadam na to pytanie. (Nie mogę odpowiedzieć w komentarzu, ponieważ muszę wysłać kod).
Może zwracać wartość null pomiędzy dwoma zdarzeniami: (1) klasa jest ładowana i (2) tworzony jest obiekt tej klasy. Oto przykład:
Uruchommy kod:
Drugi wiersz pokazuje, że instancja Y.xinstance i X.yinstance ma wartość NULL ; są one puste, ponieważ zmienne X.xinstance i Y.yinstance zostały odczytane, gdy były puste.
Czy można to naprawić? Tak,
a ten kod nie wykazuje anomalii:
ALE nie jest to opcja dla
Application
obiektu z Androidem : programista nie kontroluje czasu jego utworzenia.Jeszcze raz: różnica między pierwszym przykładem a drugim polega na tym, że drugi przykład tworzy instancję, jeśli wskaźnik statyczny ma wartość NULL. Ale programista nie może tworzyć z Androidem obiektu aplikacji zanim system zdecyduje się to zrobić.
AKTUALIZACJA
Jeszcze jeden zagadkowy przykład, w którym znajdują się zainicjowane pola statyczne
null
.Main.java :
I dostajesz:
Pamiętaj, że nie można przenieść deklaracji zmiennej statycznej o jeden wiersz wyżej, kod nie zostanie skompilowany.
źródło
Klasa zastosowania:
Zadeklaruj aplikację w AndroidManifest:
Stosowanie:
źródło
Próbujesz utworzyć opakowanie, aby uzyskać kontekst aplikacji, ale istnieje możliwość, że zwróci on
null
wskaźnik.Zgodnie z moim rozumieniem, wydaje mi się, że jest to lepsze podejście do call-any z 2
Context.getApplicationContext()
lubActivity.getApplication()
.źródło
To dobre podejście. Ja też go używam. Sugerowałbym jedynie przesłonięcie,
onCreate
aby ustawić singleton zamiast używania konstruktora.A skoro wspomniałeś
SQLiteOpenHelper
: WonCreate ()
możesz również otworzyć bazę danych.Osobiście uważam, że dokumentacja niesłusznie mówi, że zwykle nie ma potrzeby podklasy aplikacji . Myślę, że jest odwrotnie: zawsze należy podklasować aplikację.
źródło
Chciałbym użyć kontekstu aplikacji, aby uzyskać konstruktor usługi systemowej. Ułatwia to testowanie i zapewnia korzyści ze składu
Klasa testowa użyłaby wtedy przeciążonego konstruktora.
Android użyłby domyślnego konstruktora.
źródło
Podoba mi się, ale zamiast tego zaproponowałbym singleton:
źródło
new
sam aplikować (z możliwym wyjątkiem testów jednostkowych). System operacyjny to zrobi. Nie powinieneś także mieć konstruktora. Po toonCreate
jest.Używam tego samego podejścia, proponuję napisać singleton nieco lepiej:
ale nie używam wszędzie, używam
getContext()
igetApplicationContext()
gdzie mogę to zrobić!źródło