Po co rozszerzać klasę aplikacji na Androida?


168

Rozszerzona Applicationklasa może deklarować zmienne globalne. Czy są inne powody?


To tylko pomysł z góry mojej głowy, ale powinieneś być w stanie nadpisać onCreate i wyświetlić jednorazowy ekran startowy zamiast MainActivity, tj. Ekran wprowadzający, gdy użytkownik po raz pierwszy otworzy aplikację.
btse

Odpowiedzi:


29

Nie mogę wymyślić prawdziwego scenariusza, w którym rozszerzenie Aplikacji jest lepsze od innego podejścia lub konieczne do osiągnięcia czegoś. Jeśli masz drogi, często używany obiekt, możesz go zainicjować w IntentService, gdy wykryjesz, że obiekt nie jest obecnie obecny. Sama aplikacja działa w wątku interfejsu użytkownika, podczas gdy IntentService działa we własnym wątku.

Wolę przekazywać dane z działania do działania z wyraźnymi intencjami lub używać SharedPreferences. Istnieją również sposoby przekazywania danych z fragmentu do jego działania nadrzędnego przy użyciu interfejsów.


39
Istnieje wiele zastosowań rozszerzania klasy aplikacji. Jednym z bardzo przydatnych jest wyłapanie wszystkich nieprzechwyconych wyjątków w aplikacji. Więc to jest coś, co może być bardzo przydatne
png

3
Jak to robisz?
serj

8
+1 dla "prefer to pass data from Activity to Activity with explicit Intents, or use SharedPreferences". Powinniśmy zawsze eliminować stan globalny tak bardzo, jak tylko możemy i używać standardowych narzędzi Androida do globalnego zarządzania stanem zamiast statycznych zmiennych / singletonów itp.
Oleksandr Karaberov

9
czemu? przygotować się na Androida w pewnym momencie, uruchamiając je w różnych procesach lub czymkolwiek, a każdy komponent może być ponownie używany przez dowolną aplikację, podczas gdy jest to celowo ograniczone? samo przekazanie obiektów danych zamiast ich serializacji oszczędza procesor i pamięć. Paczkowanie rzeczy do przekazania w ramach procesu na tym samym urządzeniu nie jest w żaden sposób idealne. Naprawdę nie widzę sensu używania intentservice w ten sposób (po prostu zrób drugi wątek z nowym). naprawdę wiele rzeczy, które dezorientują programistów, pochodzi z tego, że prawie wszyscy dodani przez Google „pomocnicy” są tworzeni tak, jakby działania były wykonywane na oddzielnych komputerach.
Lassi Kinnunen

127

Wprowadzenie:

wprowadź opis obrazu tutaj

  1. Jeśli weźmiemy pod uwagę apkplik w naszym telefonie komórkowym, składa się on z wielu przydatnych bloków, takich jak, Activitys, Services i inne.
  2. Te komponenty nie komunikują się ze sobą regularnie i nie zapominaj, że mają swój własny cykl życia. które wskazują, że mogą być one aktywne w jednym momencie, a nieaktywne w innym momencie.

Wymagania:

  1. Czasami możemy wymagać scenariusza, w którym musimy uzyskać dostęp do zmiennej i jej stanów w całym zakresie, Applicationniezależnie od tego, z Activityktórego korzysta użytkownik,
  2. Przykładem jest to, że użytkownik może potrzebować dostępu do zmiennej, która przechowuje jego informacje personalne (np. Nazwisko), do których musi mieć dostęp poprzez Application,
  3. Możemy używać SQLite, ale tworzenie Cursori zamykanie go wielokrotnie nie jest dobre pod względem wydajności,
  4. Moglibyśmy użyć Intents do przekazania danych, ale jest to niezdarne, a sama aktywność może nie istnieć w pewnym scenariuszu, w zależności od dostępności pamięci.

Zastosowania klasy aplikacji:

  1. Dostęp do zmiennych w całym Application,
  2. Możesz użyć Applicationdo uruchomienia pewnych rzeczy, takich jak analiza itp., Ponieważ klasa aplikacji jest uruchamiana przed uruchomieniem Activitys lub Servicess,
  3. Istnieje nadpisana metoda o nazwie onConfigurationChanged (), która jest wyzwalana po zmianie konfiguracji aplikacji (poziomej na pionową i odwrotnie),
  4. Istnieje również zdarzenie o nazwie onLowMemory (), które jest wyzwalane, gdy na urządzeniu z systemem Android zaczyna brakować pamięci.

W części dotyczącej wymagań, dlaczego nie użyć SharedPreferences?

W pierwszym przykładzie, takim jak zapisywanie informacji osobistych, można użyć SharedPreferences. Ale przykłady, które podałeś w ostatniej części, rozwiały moje wątpliwości. Dzięki!
Saurabh Singh

63

Klasa aplikacji to obiekt, który ma pełny cykl życia aplikacji. To twoja najwyższa warstwa jako aplikacja. Przykładowe możliwe zastosowania:

  • Możesz dodać to, czego potrzebujesz, gdy aplikacja jest uruchamiana, zastępując onCreate w klasie Application.

  • przechowują zmienne globalne, które przechodzą od działania do działania. Jak Asynctask.

    itp


4
Używanie aplikacji jako wysypiska dla zmiennych globalnych aplikacji to nieprzyjemny zapach kodu. Aby to osiągnąć, należy użyć własnych niestandardowych, bardziej szczegółowych klas jako pojedynczych lub ze zmiennymi statycznymi.
Austin

5
@Austin dlaczego to zapach?
Relm

1
Tak, po co wąchać? Jak wspomniano wcześniej, klasa Application znajduje się na szczycie hierarchii i mogę założyć się o moje pieniądze na lunch, że niestandardowa klasa singleton jest poniżej niej. Tak więc, jeśli dojdzie do popychania, a twój telefon ma mało pamięci, powiedziałbym, że niestandardowy singleton jest pierwszym, który zostanie zabity, a nie klasa Application (która w zasadzie jest całą twoją aplikacją).
Starwave

31

Czasami chcesz przechowywać dane, takie jak zmienne globalne, do których trzeba uzyskać dostęp z wielu działań - czasami wszędzie w aplikacji. W takim przypadku pomoże Ci obiekt Application.

Na przykład, jeśli chcesz uzyskać podstawowe dane uwierzytelniające dla każdego żądania http , możesz zaimplementować metody uwierzytelniania danych w obiekcie aplikacji.

Następnie możesz uzyskać nazwę użytkownika i hasło w dowolnej z takich czynności:

MyApplication mApplication = (MyApplication)getApplicationContext();
String username = mApplication.getUsername();
String password = mApplication.getPassword();

I na koniec pamiętaj, aby używać obiektu Application jako obiektu pojedynczego:

 public class MyApplication extends Application {
    private static MyApplication singleton;

    public MyApplication getInstance(){
        return singleton;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        singleton = this;
    }
}

Aby uzyskać więcej informacji, kliknij opcję Klasa aplikacji


2
uprzejmie wyjaśnij mi, dlaczego musimy jawnie utworzyć obiekt pojedynczy klasy Application, o ile wiem, że sam jest singletonem. Czy możemy stworzyć wiele obiektów aplikacji, jeśli możemy, to w jaki sposób? i jakie są tego konsekwencje? Uprzejmie wyjaśnij.
Syed Raza Mehdi

Nie, prawdopodobnie tylko jedna klasa aplikacji. developer.android.com/guide/topics/manifest/ ...
IntelliJ Amiya

więc dlaczego musimy jawnie utrzymywać pojedynczy obiekt tego? Czy system operacyjny nie obsługuje go za nas? Właściwie napotkałem kod, w którym znajduje się obiekt aplikacji utworzony w klasie aktywności i nie jest on wymieniany w manifeście. Myślę, że to źle, jestem również ciekawy, dlaczego tworzymy statyczny obiekt singletonowy. To, co myślisz, jest najlepszym podejściem. Dzięki za odpowiedź.
Syed Raza Mehdi

1
dzięki Znalazłem odpowiedź tutaj pod tym linkiem developer.android.com/reference/android/app/Application.html
Syed Raza Mehdi

Gdzie jest obiekt * singleton * w tym
Dr. aNdRO

8

Klasa Application to singleton, do którego można uzyskać dostęp z dowolnego działania lub z dowolnego miejsca, w którym znajduje się obiekt Context.

Dostajesz także trochę cyklu życia.

Możesz użyć metody onCreate aplikacji, aby utworzyć wystąpienia drogich, ale często używanych obiektów, takich jak pomocnik analityczny. Wtedy możesz uzyskać dostęp do tych obiektów i korzystać z nich wszędzie.


6
„Otrzymujesz także trochę cyklu życia”. możesz to przeredagować.
wtsang02

2
Mam na myśli, że otrzymujesz kilka wezwań dotyczących cyklu życia, ale nie tak często, jak w przypadku działania lub fragmentu. Na przykład nie ma onDestroy () dla klasy Application.
Jon F Hancock

Czy ta klasa jest tworzona automatycznie?
Konstantin Konopko

Tak. O ile określisz go poprawnie w pliku AndroidManifest.xml.
Jon F Hancock

Nie, nie jest tworzony automatycznie, musisz go utworzyć, a następnie zadeklarować w swoim pliku manifestu
Ojonugwa Jude Ochalifu

7

Najlepsze wykorzystanie klasy aplikacji. Przykład: Załóżmy, że musisz ponownie uruchomić menedżera alarmów po zakończeniu rozruchu.

public class BaseJuiceApplication extends Application implements BootListener {

    public static BaseJuiceApplication instance = null;

    public static Context getInstance() {
        if (null == instance) {
            instance = new BaseJuiceApplication();
        }
        return instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();


    }

    @Override
    public void onBootCompleted(Context context, Intent intent) {
        new PushService().scheduleService(getInstance());
        //startToNotify(context);
    }

Zastanawiam się, dlaczego musimy utworzyć statyczną referencję do obiektu aplikacji, skąd możemy ją pobrać za pomocą metody getApplication () i typecastować ją do klasy aplikacji. O ile zrozumiałem tę koncepcję, klasa aplikacji jest tworzona przez sam system operacyjny i powinna mieć tylko jedną instancję obsługiwaną przez system operacyjny. Uprzejmie wyjaśnij, dzięki.
Syed Raza Mehdi,

Masz rację. Wywołanie getApplication z dowolnego składnika aplikacji w aplikacji zwraca pojedyncze wystąpienie pochodne aplikacji, które jest Twoją aplikacją. Jest to obsługiwane wewnętrznie przez platformę Android. Wszystko, co musisz zrobić, to rzutować zwróconą instancję na niestandardową klasę rozszerzającą Application. Musisz również odpowiednio ustawić swój manifest, tak aby odpowiednia klasa była używana przez platformę Android do tworzenia wystąpienia instancji.
Matt Welke,

5

To nie odpowiedź, ale obserwacja : pamiętaj, że dane w rozszerzonym obiekcie aplikacji nie powinny być powiązane z instancją działania, ponieważ możliwe jest, że masz jednocześnie uruchomione dwie instancje tej samej czynności (jedną w pierwszy plan i jeden niewidoczny) .

Na przykład, zaczynasz swoją aktywność normalnie w programie uruchamiającym, a następnie „minimalizujesz” go. Następnie uruchamiasz inną aplikację (np. Tasker), która uruchamia kolejną instancję Twojej aktywności, na przykład w celu utworzenia skrótu, ponieważ Twoja aplikacja obsługuje android.intent.action.CREATE_SHORTCUT. Jeśli następnie utworzony zostanie skrót i to wywołanie działania tworzącego skrót zmodyfikuje dane obiektu aplikacji, to działanie działające w tle zacznie używać tego zmodyfikowanego obiektu aplikacji po przywróceniu go na pierwszy plan.


4

Widzę, że na to pytanie brakuje odpowiedzi. Rozszerzam, Applicationponieważ używam implementacji Billa Pugh Singleton ( patrz odniesienie ), a niektóre z moich singletonów wymagają kontekstu. Do Applicationklasy wygląda następująco:

public class MyApplication extends Application {

    private static final String TAG = MyApplication.class.getSimpleName();

    private static MyApplication sInstance;

    @Contract(pure = true)
    @Nullable
    public static Context getAppContext() {
        return sInstance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate() called");
        sInstance = this;
    }
}

A singletony wyglądają tak:

public class DataManager {

    private static final String TAG = DataManager.class.getSimpleName();

    @Contract(pure = true)
    public static DataManager getInstance() {
        return InstanceHolder.INSTANCE;
    }

    private DataManager() {
        doStuffRequiringContext(MyApplication.getAppContext());
    }

    private static final class InstanceHolder {
        @SuppressLint("StaticFieldLeak")
        private static final DataManager INSTANCE = new DataManager();
    }
}

W ten sposób nie muszę mieć kontekstu za każdym razem, gdy używam singletona i uzyskuję leniwą synchronizowaną inicjalizację z minimalną ilością kodu.

Wskazówka: aktualizacja szablonu singleton Android Studio pozwala zaoszczędzić dużo czasu.


3

Myślę, że możesz używać klasy Application do wielu rzeczy, ale wszystkie one są związane z twoją potrzebą wykonania pewnych czynności PRZED rozpoczęciem jakichkolwiek działań lub usług. Na przykład w mojej aplikacji używam niestandardowych czcionek. Zamiast dzwonić

Typeface.createFromAsset()

z każdego działania, aby uzyskać referencje do moich czcionek z folderu Assets (jest to złe, ponieważ spowoduje to wyciek pamięci, ponieważ zachowujesz odwołanie do zasobów za każdym razem, gdy wywołasz tę metodę), robię to z onCreate()metody w mojej klasie Application :

private App appInstance;
Typeface quickSandRegular;
...
public void onCreate() {
    super.onCreate();

    appInstance = this;
    quicksandRegular = Typeface.createFromAsset(getApplicationContext().getAssets(),
                       "fonts/Quicksand-Regular.otf");
   ...
   }

Teraz mam również metodę zdefiniowaną w ten sposób:

public static App getAppInstance() {
    return appInstance;
}

i to:

public Typeface getQuickSandRegular() {
    return quicksandRegular;
}

Tak więc z dowolnego miejsca w mojej aplikacji wszystko, co muszę zrobić, to:

App.getAppInstance().getQuickSandRegular()

Kolejnym zastosowaniem dla mnie klasy Application jest sprawdzenie, czy urządzenie jest podłączone do Internetu PRZED czynnościami i usługami wymagającymi połączenia faktycznie rozpoczną się i podejmą niezbędne działania.


1
Dobrze powiedziane. Bardzo ładne załamanie.
Oluwatobi Adenekan

3

Źródło: https://github.com/codepath/android_guides/wiki/Understanding-the-Android-Application-Class

W wielu aplikacjach nie ma potrzeby bezpośredniej pracy z klasą aplikacji. Istnieje jednak kilka dopuszczalnych zastosowań niestandardowej klasy aplikacji:

  • Specjalistyczne zadania, które należy wykonać przed utworzeniem pierwszego działania
  • Globalna inicjalizacja, która musi być współdzielona przez wszystkie komponenty (raportowanie awarii, trwałość)
  • Metody statyczne zapewniające łatwy dostęp do statycznych niezmiennych danych, takich jak udostępniony obiekt klienta sieci

Nigdy nie należy przechowywać danych instancji mutowalnych wewnątrz obiektu Application, ponieważ jeśli założymy, że dane tam pozostaną, aplikacja nieuchronnie ulegnie awarii w pewnym momencie z wyjątkiem NullPointerException. Nie ma gwarancji, że obiekt aplikacji pozostanie w pamięci na zawsze, zostanie zabity. Wbrew powszechnemu przekonaniu aplikacja nie zostanie ponownie uruchomiona od zera. Android utworzy nowy obiekt Application i rozpocznie działanie, w którym użytkownik był wcześniej, dając złudzenie, że aplikacja nigdy nie została zabita.


1

Możesz uzyskać dostęp do zmiennych dowolnej klasy bez tworzenia obiektów, jeśli jest rozszerzony przez Application. Można je wywoływać globalnie, a ich stan jest utrzymywany, dopóki aplikacja nie zostanie zabita.


1

Użycie aplikacji rozszerzającej sprawia, że ​​aplikacja jest pewna dla każdego rodzaju operacji, które chcesz przez cały okres jej działania. Teraz może to być dowolny rodzaj zmiennych i przypuśćmy, że jeśli chcesz pobrać jakieś dane z serwera, możesz umieścić swoje asynchroniczne zadanie w aplikacji, aby pobierało się za każdym razem i ciągle, dzięki czemu automatycznie otrzymasz zaktualizowane dane. Użyj tego linku po więcej wiedzy ...

http://www.intridea.com/blog/2011/5/24/how-to-use-application-object-of-android


nie jest to wątek, więc „dla dowolnego rodzaju operacji, które chcesz wykonać przez cały okres działania aplikacji”. to nie jest prawda.
Lassi Kinnunen

1

Aby dodać do innych odpowiedzi stwierdzających, że możesz chcieć przechowywać zmienne w zakresie aplikacji, dla dowolnych długo działających wątków lub innych obiektów, które wymagają powiązania z twoją aplikacją, w której NIE używasz działania (aplikacja nie jest działaniem). na przykład brak możliwości zażądania powiązanej usługi .. wtedy preferowane jest powiązanie z instancją aplikacji. Jedynym oczywistym ostrzeżeniem związanym z tym podejściem jest to, że obiekty żyją tak długo, jak działa aplikacja, więc wymagana jest bardziej niejawna kontrola nad pamięcią, w przeciwnym razie napotkasz problemy związane z pamięcią, takie jak wycieki.

Innym przydatnym może być to, że w kolejności operacji aplikacja jest uruchamiana jako pierwsza przed jakąkolwiek czynnością. W tych ramach czasowych możesz przygotować wszelkie niezbędne czynności porządkowe, które miałyby miejsce przed twoją pierwszą czynnością, jeśli sobie tego życzysz.

2018-10-19 11:31:55.246 8643-8643/: application created
2018-10-19 11:31:55.630 8643-8643/: activity created
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.