Jak zadeklarować zmienne globalne w Androidzie?


595

Tworzę aplikację, która wymaga logowania. Utworzyłem główną aktywność i logowanie.

W onCreatemetodzie głównej aktywności dodałem następujący warunek:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ...

    loadSettings();
    if(strSessionString == null)
    {
        login();
    }
    ...
}

onActivityResultMetoda, która jest wykonywana, gdy formularz logowania kończy wygląda następująco:

@Override
public void onActivityResult(int requestCode,
                             int resultCode,
                             Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode)
    {
        case(SHOW_SUBACTICITY_LOGIN):
        {
            if(resultCode == Activity.RESULT_OK)
            {

                strSessionString = data.getStringExtra(Login.SESSIONSTRING);
                connectionAvailable = true;
                strUsername = data.getStringExtra(Login.USERNAME);
            }
        }
    }

Problem polega na tym, że formularz logowania pojawia się czasami dwukrotnie ( login()metoda jest wywoływana dwukrotnie), a także, gdy klawiatura telefonu przesuwa się, formularz logowania pojawia się ponownie i myślę, że problem jest zmienny strSessionString.

Czy ktoś wie, jak ustawić zmienną globalną, aby uniknąć wyświetlania formularza logowania po pomyślnym uwierzytelnieniu użytkownika?


dobry samouczek dotyczący obsługi stanu aktywności za pomocą pakietu stanu zapisanych instancji quicktips.in/…
Deepak Swami

Odpowiedzi:


954

Napisałem tę odpowiedź jeszcze w 2009 roku, kiedy Android był stosunkowo nowy i było wiele słabo rozwiniętych obszarów w rozwoju Androida. Dodałem długi aneks na dole tego postu, odnosząc się do pewnej krytyki i wyszczególniając filozoficzne nieporozumienie, które mam z wykorzystaniem Singletonów zamiast Podklasy Klasy. Przeczytaj na własne ryzyko.

ORYGINALNA ODPOWIEDŹ:

Bardziej ogólnym problemem, jaki napotykasz, jest sposób zapisywania stanu w kilku działaniach i we wszystkich częściach aplikacji. Zmienna statyczna (na przykład singleton) jest powszechnym sposobem osiągnięcia tego celu w Javie. Odkryłem jednak, że bardziej eleganckim sposobem w Androidzie jest powiązanie swojego stanu z kontekstem aplikacji.

Jak wiadomo, każde działanie jest również kontekstem, który jest informacją o jego środowisku wykonywania w najszerszym tego słowa znaczeniu. Twoja aplikacja ma również kontekst, a Android gwarantuje, że będzie istnieć jako pojedyncza instancja w całej aplikacji.

Można to zrobić, tworząc własną podklasę android.app.Application , a następnie określ tę klasę w znaczniku aplikacji w swoim manifeście. Teraz Android automatycznie utworzy instancję tej klasy i udostępni ją dla całej aplikacji. Możesz uzyskać do niego dostęp za contextpomocą dowolnej Context.getApplicationContext()metody ( Activityzapewnia również metodę, getApplication()która ma dokładnie taki sam efekt). Poniżej znajduje się niezwykle uproszczony przykład z zastrzeżeniami do naśladowania:

class MyApp extends Application {

  private String myState;

  public String getState(){
    return myState;
  }
  public void setState(String s){
    myState = s;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    ...
    MyApp appState = ((MyApp)getApplicationContext());
    String state = appState.getState();
    ...
  }
}

Ma to zasadniczo taki sam efekt, jak użycie zmiennej statycznej lub singletonu, ale całkiem dobrze integruje się z istniejącą strukturą Androida. Pamiętaj, że to nie zadziała w różnych procesach (jeśli Twoja aplikacja będzie jednym z rzadkich, który ma wiele procesów).

Warto zwrócić uwagę na powyższy przykład; załóżmy, że zamiast tego zrobiliśmy coś takiego:

class MyApp extends Application {

  private String myState = /* complicated and slow initialization */;

  public String getState(){
    return myState;
  }
}

Teraz ta powolna inicjalizacja (np. Uderzanie w dysk, uderzanie w sieć, blokowanie czegokolwiek itp.) Będzie wykonywana za każdym razem, gdy aplikacja zostanie utworzona! Możesz pomyśleć, że to tylko jeden raz na proces, a ja i tak będę musiał zapłacić koszt, prawda? Na przykład, jak wspomina Dianne Hackborn, jest całkowicie możliwe, że Twój proces zostanie utworzony - tylko - do obsługi zdarzenia transmisji w tle. Jeśli przetwarzanie transmisji nie potrzebuje tego stanu, potencjalnie wykonałeś całą serię skomplikowanych i powolnych operacji za darmo. Leniwa instancja to tutaj nazwa gry. Poniżej przedstawiono nieco bardziej skomplikowany sposób korzystania z aplikacji, który ma sens tylko w przypadku najprostszych zastosowań:

class MyApp extends Application {

  private MyStateManager myStateManager = new MyStateManager();

  public MyStateManager getStateManager(){
    return myStateManager ;
  }
}

class MyStateManager {

  MyStateManager() {
    /* this should be fast */
  }

  String getState() {
    /* if necessary, perform blocking calls here */
    /* make sure to deal with any multithreading/synchronicity issues */

    ...

    return state;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    ...
    MyStateManager stateManager = ((MyApp)getApplicationContext()).getStateManager();
    String state = stateManager.getState();
    ...
  }
}

Podczas gdy wolę podklasę aplikacji niż używanie tutaj singletonów jako bardziej eleganckiego rozwiązania, wolę programiści używają singletonów, jeśli jest to naprawdę konieczne, zamiast nie myśleć w ogóle o wydajności i wielowątkowych implikacjach skojarzenia stanu z podklasą aplikacji.

UWAGA 1: Również, jak skomentowano, w celu poprawnego powiązania zastąpienia aplikacji z aplikacją, w pliku manifestu niezbędny jest tag. Ponownie zobacz dokumentację Androida, aby uzyskać więcej informacji. Przykład:

<application
     android:name="my.application.MyApp" 
     android:icon="..."
     android:label="...">
</application>

UWAGA 2: użytkownik 608578 pyta poniżej, jak to działa z zarządzaniem cyklami życia natywnych obiektów. Nie jestem w stanie w najmniejszym stopniu korzystać z natywnego kodu w Androidzie i nie mam kwalifikacji, aby odpowiedzieć na to, jak to współdziałałoby z moim rozwiązaniem. Jeśli ktoś ma odpowiedź na to pytanie, jestem skłonny je podziękować i umieścić informacje w tym poście dla maksymalnej widoczności.

UZUPEŁNIENIE:

Jak zauważyli niektórzy, nie jest to rozwiązanie dla stanu trwałego , coś, co być może powinienem był bardziej podkreślić w pierwotnej odpowiedzi. Oznacza to, że nie jest to rozwiązanie do zapisywania informacji o użytkownikach lub innych, które mają być utrwalane przez cały czas istnienia aplikacji. Dlatego uważam, że większość krytyki poniżej związanej z zabijaniem aplikacji w dowolnym momencie itp., Jest dyskusyjna, ponieważ wszystko, co kiedykolwiek wymagało utrwalenia na dysku, nie powinno być przechowywane przez podklasę aplikacji. Ma to być rozwiązanie do przechowywania tymczasowego, łatwego do odtworzenia stanu aplikacji (na przykład, czy użytkownik jest zalogowany) i komponentów, które są z natury pojedynczymi instancjami (na przykład menedżerem sieci aplikacji) ( NIE singletonem!).

Dayerman był na tyle uprzejmy, aby wskazać na interesującą rozmowę z Reto Meier i Dianne Hackborn, w której odradza się stosowanie podklas aplikacji na rzecz wzorców Singletona. Somatik zwrócił też uwagę na coś takiego wcześniej, chociaż wtedy tego nie widziałem. Ze względu na rolę Reto i Dianne w utrzymywaniu platformy Android, w dobrej wierze nie mogę zalecić ignorowania ich rad. Co mówią, idzie. Nie zgadzam się z opiniami wyrażonymi w odniesieniu do preferowania Singleton nad podklasami aplikacji. W moim sporze wykorzystam koncepcje najlepiej wyjaśnione w tym objaśnieniu StackExchange wzorca projektowego Singleton, aby nie musiałem definiować terminów w tej odpowiedzi. Gorąco zachęcam do przejrzenia linku przed kontynuowaniem. Punkt po punkcie:

Dianne stwierdza: „Nie ma powodu, aby podklasować z aplikacji. Nie różni się to od utworzenia singletonu ...” To pierwsze twierdzenie jest nieprawidłowe. Istnieją dwa główne powody tego. 1) Klasa aplikacji zapewnia lepszą dożywotnią gwarancję twórcy aplikacji; gwarantowana jest żywotność aplikacji. Singleton nie jest WYŁĄCZNIE związany z czasem życia aplikacji (chociaż jest efektywny). Może to nie stanowić problemu dla przeciętnego programisty aplikacji, ale twierdzę, że jest to dokładnie rodzaj umowy, którą powinien oferować interfejs API systemu Android, i zapewnia on także znacznie większą elastyczność systemowi Android, minimalizując czas życia powiązanego dane. 2) Klasa Application udostępnia twórcy aplikacji z uchwytem pojedynczej instancji dla stanu, co bardzo różni się od posiadacza stanu Singleton. Aby zobaczyć listę różnic, zobacz link objaśniający Singleton powyżej.

Dianne kontynuuje: „... prawdopodobnie będzie to coś, czego będziesz żałować w przyszłości, gdy odkryjesz, że obiekt aplikacji staje się tym wielkim splątanym bałaganem z powodu niezależnej logiki aplikacji”. Z pewnością nie jest to niepoprawne, ale nie jest to powód, aby wybierać Singleton zamiast podklasy aplikacji. Żaden z argumentów Diane nie podaje powodu, dla którego użycie Singletona jest lepsze niż podklasa aplikacji, wszystko, co próbuje ustalić, to, że użycie singletonu nie jest gorsze niż podklasa aplikacji, co moim zdaniem jest fałszywe.

Kontynuuje: „A to bardziej naturalnie prowadzi do tego, jak powinieneś zarządzać tymi rzeczami - inicjowanie ich na żądanie”. Ignoruje to fakt, że nie ma powodu, dla którego nie można zainicjować na żądanie przy użyciu podklasy aplikacji. Znowu nie ma różnicy.

Dianne kończy się słowami: „Sama platforma ma mnóstwo ton singletonów dla wszystkich małych współużytkowanych danych, które utrzymuje dla aplikacji, takich jak pamięci podręczne załadowanych zasobów, pule obiektów itp. Działa świetnie”. Nie twierdzę, że używanie Singletonów nie działa dobrze lub nie jest uzasadnioną alternatywą. Argumentuję, że Singletony nie zawierają tak silnej umowy z systemem Android jak przy użyciu podklasy aplikacji, a ponadto, że używanie Singletonów ogólnie wskazuje na nieelastyczną konstrukcję, której nie można łatwo modyfikować i prowadzi do wielu problemów w przyszłości. IMHO, silna umowa, którą Android API oferuje aplikacjom dla programistów, jest jednym z najbardziej atrakcyjnych i przyjemnych aspektów programowania w Androidzie i pomogła w szybkim wdrożeniu programistów, co doprowadziło platformę Android do sukcesu, jaki osiągnęła dzisiaj.

Dianne również skomentował poniżej, wspominając o dodatkowej wadzie korzystania z podklas Aplikacji, mogą zachęcać lub ułatwiać pisanie kodu o mniejszej wydajności. Jest to bardzo prawdziwe i zedytowałem tę odpowiedź, aby podkreślić znaczenie rozważenia perf i przyjęcia właściwego podejścia, jeśli używasz podklasy aplikacji. Jak twierdzi Dianne, należy pamiętać, że twoja klasa aplikacji będzie tworzona za każdym razem, gdy proces zostanie załadowany (może być wiele razy na raz, jeśli aplikacja działa w wielu procesach!), Nawet jeśli proces jest ładowany tylko dla emisji w tle zdarzenie. Dlatego ważne jest, aby używać klasy Application raczej jako repozytorium wskaźników do współużytkowanych komponentów aplikacji, a nie jako miejsce do przetwarzania!

Pozostawiam wam następującą listę wad singletonów, skradzionych z wcześniejszego linku StackExchange:

  • Niemożność korzystania z klas abstrakcyjnych lub interfejsowych;
  • Niemożność podziału na podklasy;
  • Wysokie sprzężenie w aplikacji (trudne do modyfikacji);
  • Trudne do przetestowania (nie można fałszować / wyśmiewać w testach jednostkowych);
  • Trudne do zrównoleglenia w przypadku stanu zmiennego (wymaga szerokiego blokowania);

i dodaj własne:

  • Niejasna i niemożliwa do zarządzania umowa na całe życie, nieodpowiednia dla rozwoju Androida (lub większości innych);

93
Dziękuję wkrótce - tego rodzaju odpowiedzi są powodem, dla którego tak bardzo kocham Stack Overflow. DOBRA ROBOTA!
JohnnyLambada,

5
Dla każdego, kto zastanawia się, jak „określić tę klasę w znaczniku aplikacji w swoim manifeście”, w tym piśmie istnieją dwie inne odpowiedzi na to pytanie, które opisują, jak to zrobić (użyj Androida: nazwa), jedna przez ebuprofen i jedna autor: Mike Brown.
Tyler Collier

9
Wkrótce twoja odpowiedź jest prawidłowa, ale czy zauważyłeś, że powinniśmy dodać <application android: name = ". MyApp" ... /> do pliku manifestu Androida?
anticafe

12
Powtórzę raz jeszcze, nie powinieneś używać aplikacji do globałów. Jest bezużyteczny, nie daje korzyści w porównaniu z singletonami i może być aktywnie szkodliwy, na przykład szkodzić wydajności uruchamiania procesu. Podczas tworzenia aplikacji nie masz pojęcia, do czego tworzony jest proces. Leniwie inicjalizując singletony w razie potrzeby, wystarczy wykonać niezbędną pracę. Na przykład, jeśli proces jest uruchamiany w celu obsługi transmisji o jakimś zdarzeniu w tle, nie ma powodu, aby inicjalizować stan globalny wymagany przez interfejs użytkownika.
hackbod

14
Wyjaśnijmy też tutaj - wszystkie twoje argumenty przeciwko singletonom są całkowicie uzasadnione, kiedy mówimy o sytuacjach, w których faktycznie wybierasz między singletonem a innym podejściem, które nie jest globalne; singletony to globale, z wszystkimi zastrzeżeniami dotyczącymi globali, które mają zastosowanie. Jednak aplikacja jest również singletonem . Nie uciekasz przed tymi problemami, przechodząc do aplikacji podklasowania, aplikacja jest dokładnie taka sama jak singleton (ale gorzej), pozwala jedynie oszukać siebie, że robisz coś bardziej czystego. Ale ty nie jesteś.
hackbod

153

Utwórz tę podklasę

public class MyApp extends Application {
  String foo;
}

W AndroidManifest.xml dodaj android: name

Przykład

<application android:name=".MyApp" 
       android:icon="@drawable/icon" 
       android:label="@string/app_name">

1
Dziękuję za to. Zastanawiałem się, jak to zadeklarować w manifeście
Ktoś gdzieś

3
Aby to zadziałało, musiałem usunąć „.” w ramach „.MyApp”
Ktoś gdzieś

3
po prostu zadeklaruj to po głównej aktywności, w przeciwnym razie może się nie zainstalować / wdrożyć
sami

11
chcę tylko powiedzieć, że to idzie w znaczniku aplikacji MAIN, który już tam jest ... to nie jest drugi :) musiał nauczyć się na własnej skórze.
bwoogie

java.lang.IllegalAccessException: access to class is not allowed
Raptor,

142

Sugerowany przez Soonil sposób utrzymania stanu aplikacji jest dobry, jednak ma jeden słaby punkt - zdarzają się przypadki, gdy system operacyjny zabija cały proces aplikacji. Oto dokumentacja na ten temat - Procesy i cykle życia .

Rozważ przypadek - Twoja aplikacja przechodzi w tło, ponieważ ktoś do Ciebie dzwoni (aplikacja Telefon jest teraz na pierwszym planie). W takim przypadku && pod pewnymi innymi warunkami (sprawdź powyższy link, aby dowiedzieć się, jakie mogą być), system operacyjny może zabić proces aplikacji, w tym Applicationinstancję podklasy. W rezultacie stan zostaje utracony. Gdy później wrócisz do aplikacji, system operacyjny przywróci stos aktywności i Applicationinstancję podklasy, jednak myStatepole to będzie null.

AFAIK, jedynym sposobem na zagwarantowanie bezpieczeństwa stanu jest użycie dowolnego rodzaju utrwalania stanu, np. Użycie prywatnego dla pliku aplikacji lub SharedPrefernces(w końcu używa prywatnego dla pliku aplikacji w wewnętrznym systemie plików).


10
+1 za pozostawanie przy SharedPreferences; tak to widziałem. Wydaje mi się dziwne nadużywanie systemu preferencji dla zapisanego stanu, ale działa tak dobrze, że kwestia staje się kwestią terminologii.
Cheezmeister

1
czy mógłbyś napisać kod (lub podać link do wyjaśnienia), w jaki sposób SharedPreferences jest używany do rozwiązania problemu opisanego przez Arhimeda
Ktoś Gdzieś

2
Preferencje, baza danych, serializacja plików itp. Każde działanie może utrzymać stan, jeśli użyje onSaveInstanceState, ale to nie pomoże, jeśli użytkownik wycofa się z działania i usunie je ze stosu historii, wymusi zamknięcie lub wyłączenie urządzenia .
Darren Hinderer

1
To zachowanie jest bardzo denerwujące - nie byłoby takie złe, gdyby wywołano metodę onTerminate () aplikacji, aby elegancko poradzić sobie z sytuacją.
Dean Wild

2
To jest poprawna odpowiedź moim zdaniem. Błędem jest poleganie na tej samej instancji aplikacji istniejącej w różnych działaniach. Z mojego doświadczenia wynika, że ​​Android dość często wybija się i odtwarza cały proces, gdy jesteś w tle. Bycie w tle może oznaczać uruchomienie intencji kamery, intencji przeglądarki lub odbieranie połączenia telefonicznego.
Jared Kells

26

Tylko uwaga ...

Dodaj:

android:name=".Globals"

lub jakkolwiek nazwałeś swoją podklasę do istniejącego <application> znacznika. Próbowałem dodawać kolejny <application>znacznik do manifestu i otrzymywałem wyjątek.


Cześć, Gimbl. Miałem ten sam problem. Miałem także własny tag <application>, a kiedy próbuję dodać kolejny tag <application>, miałem ten sam problem co Ty (komunikat wyjątku). Ale zrobiłem to, o czym wspomniałeś, i to nie zadziałało. Dodaję Androida: name = ". GlobalClass" do mojego tagu <application>, ale to nie działa. Czy potrafisz w pełni wyjaśnić, jak to rozwiązałeś?
Sonhja,

3
Dobry <manifest> <aplikacja android: name = ". GlobalData"> </application> </manifest>. Zły <manifest><application> </application> <aplikacja android: name = ". GlobalData"> </application> </manifest>
Gimbl

13

Nie mogłem też znaleźć sposobu na określenie znacznika aplikacji, ale po wielu pracach Googling stało się oczywiste z dokumentacji pliku manifestu: użyj androida: nazwa, oprócz domyślnej ikony i etykiety w sekcji aplikacji.

android: nazwa W pełni kwalifikowana nazwa podklasy aplikacji zaimplementowanej dla aplikacji. Po uruchomieniu procesu aplikacji klasa ta jest tworzona przed dowolnym składnikiem aplikacji.

Podklasa jest opcjonalna; większość aplikacji nie będzie go potrzebować. W przypadku braku podklasy system Android korzysta z instancji podstawowej klasy aplikacji.


13

Co powiesz na zapewnienie gromadzenia pamięci natywnej za pomocą takich globalnych struktur?

Działania mają onPause/onDestroy()metodę wywoływaną po zniszczeniu, ale klasa aplikacji nie ma odpowiedników. Jaki mechanizm jest zalecany, aby zapewnić, że struktury globalne (szczególnie zawierające odniesienia do pamięci natywnej) są odpowiednio usuwane, gdy aplikacja zostanie zabita lub stos zadań zostanie umieszczony w tle?


1
Oczywistym rozwiązaniem jest wdrożenie interfejsu zamykanego dla obiektów odpowiedzialnych za zasoby rodzime i zapewnienie, że są one zarządzane za pomocą instrukcji try-with-resources lub czegoś innego. W najgorszym przypadku zawsze można użyć finalizatora obiektów.
wkrótce

5

Wystarczy zdefiniować nazwę aplikacji, jak poniżej, która będzie działać:

<application
  android:name="ApplicationName" android:icon="@drawable/icon">
</application>

4

Jak wspomniano powyżej, system operacyjny może zabić APLIKACJĘ bez żadnego powiadomienia (nie ma zdarzenia onDestroy), więc nie ma możliwości zapisania tych zmiennych globalnych.

SharedPreferences może być rozwiązaniem Z WYJĄTKIEM, że masz zmienne COMPLEX STRUCTURED (w moim przypadku miałem tablicę liczb całkowitych do przechowywania identyfikatorów, które użytkownik już obsługiwał). Problem z SharedPreferences polega na tym, że trudno jest przechowywać i pobierać te struktury za każdym razem, gdy potrzebne są wartości.

W moim przypadku miałem SERVICE w tle, więc mogłem przenieść tam te zmienne, a ponieważ usługa ma zdarzenie onDestroy, mogłem łatwo zapisać te wartości.


Nie można zagwarantować, że funkcja onDestroy () zostanie wywołana nawet dla usługi.
Naucz się OpenGL ES

Tak, może się to zdarzyć, ale tylko w sytuacjach krytycznych.
Adorjan Princz

4

Jeśli niektóre zmienne są przechowywane w sqlite i musisz ich używać w większości działań w swojej aplikacji. to aplikacja może być najlepszym sposobem na osiągnięcie tego. Zapytaj o zmienne z bazy danych podczas uruchamiania aplikacji i zapisz je w polu. Następnie możesz użyć tych zmiennych w swoich działaniach.

Więc znajdź właściwą drogę, a nie ma najlepszej drogi.


3

Możesz mieć pole statyczne do przechowywania tego rodzaju stanu. Lub umieść go w pakiecie zasobów i przywróć stamtąd na onCreate (pakiet saveInstanceState). Upewnij się tylko, że całkowicie rozumiesz zarządzany cykl życia aplikacji na Androida (np. Dlaczego login () jest wywoływany przy zmianie orientacji klawiatury).


2

NIE używaj innego <application>znacznika w pliku manifestu. Po prostu dokonaj jednej zmiany w istniejącym <application>znaczniku, dodaj ten wiersz android:name=".ApplicationName"gdzie,ApplicationName będzie nazwą podklasy (używanej do przechowywania globalnego), którą zamierzasz utworzyć.

więc w końcu twój JEDEN I TYLKO <application> znacznik w pliku manifestu powinien wyglądać następująco: -

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat.NoActionBar"
        android:name=".ApplicationName"
        >

1

możesz użyć Intents, Sqlite lub Shared Preferencje. Jeśli chodzi o przechowywanie multimediów, takich jak dokumenty, zdjęcia i filmy, możesz zamiast tego utworzyć nowe pliki.


1

Możesz to zrobić za pomocą dwóch metod:

  1. Korzystanie z klasy aplikacji
  2. Korzystanie z preferencji wspólnych

  3. Korzystanie z klasy aplikacji

Przykład:

class SessionManager extends Application{

  String sessionKey;

  setSessionKey(String key){
    this.sessionKey=key;
  }

  String getSessisonKey(){
    return this.sessionKey;
  }
}

Możesz użyć wyższej klasy, aby zaimplementować logowanie w MainActivity, jak poniżej. Kod będzie wyglądał mniej więcej tak:

@override 
public void onCreate (Bundle savedInstanceState){
  // you will this key when first time login is successful.
  SessionManager session= (SessionManager)getApplicationContext();
  String key=getSessisonKey.getKey();
  //Use this key to identify whether session is alive or not.
}

Ta metoda będzie działać w przypadku tymczasowego przechowywania. Naprawdę nie masz pojęcia, kiedy system operacyjny zabije aplikację z powodu małej ilości pamięci. Gdy aplikacja znajduje się w tle, a użytkownik porusza się po innej aplikacji, która wymaga więcej pamięci do uruchomienia, aplikacja zostanie zabita, ponieważ system operacyjny ma wyższy priorytet dla procesów na pierwszym planie niż tło. Dlatego obiekt aplikacji będzie miał wartość zerową przed wylogowaniem użytkownika. Dlatego w tym celu zalecam użycie drugiej metody określonej powyżej.

  1. Korzystanie z wspólnych preferencji.

    String MYPREF="com.your.application.session"
    
    SharedPreferences pref= context.getSharedPreferences(MyPREF,MODE_PRIVATE);
    
    //Insert key as below:
    
    Editot editor= pref.edit();
    
    editor.putString("key","value");
    
    editor.commit();
    
    //Get key as below.
    
    SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
    
    String key= getResources().getString("key");

0

Po aktywacji wynik jest wywoływany przed wznowieniem. Więc przejdź do logowania, aby wznowić, a drugie logowanie może zostać zablokowane, gdy aktywność domieszki zwróci wynik pozytywny. Wznowienie jest wywoływane za każdym razem, więc nie ma obaw, że nie zostanie wywołane za pierwszym razem.


0

Podejście do podklasowania zostało również zastosowane przez środowisko BARACUS. Z mojego punktu widzenia podklasowanie Aplikacja była przeznaczona do pracy z cyklami życia Androida; To co dowolny kontener aplikacji. Zamiast mieć globale, rejestruję fasolę w tym kontekście i pozwalam jej wstrzykiwać do dowolnej klasy zarządzanej przez kontekst. Każda iniekcja fasoli jest singletonem.

Zobacz ten przykład, aby uzyskać szczegółowe informacje

Po co wykonywać pracę ręczną, skoro można mieć znacznie więcej?


0
class GlobaleVariableDemo extends Application {

    private String myGlobalState;

    public String getGlobalState(){
     return myGlobalState;
    }
    public void setGlobalState(String s){
     myGlobalState = s;
    }
}

class Demo extends Activity {

@Override
public void onCreate(Bundle b){
    ...
    GlobaleVariableDemo appState = ((GlobaleVariableDemo)getApplicationContext());
    String state = appState.getGlobalState();
    ...
    }
}

0

Możesz utworzyć klasę, która rozszerza Applicationklasę, a następnie zadeklarować zmienną jako pole tej klasy i podać dla niej metodę gettera.

public class MyApplication extends Application {
    private String str = "My String";

    synchronized public String getMyString {
        return str;
    }
}

A następnie, aby uzyskać dostęp do tej zmiennej w swoim działaniu, użyj tego:

MyApplication application = (MyApplication) getApplication();
String myVar = application.getMyString();
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.