Variabile globale Android


293

Come posso creare una variabile globale mantenendo valori per tutto il ciclo di vita dell'applicazione indipendentemente dall'attività in esecuzione.


E perché dovremmo usare set and get (Jeff Gilfelt's asnwer) ?! Perché impostiamo il valore direttamente su variabile? in questo modo: public volatile static String x; e per impostare il valore: GeneralClass.x = value;
Dr.jacky,

Risposte:


531

È possibile estendere la android.app.Applicationclasse base e aggiungere le variabili membro in questo modo:

public class MyApplication extends Application {

    private String someVariable;

    public String getSomeVariable() {
        return someVariable;
    }

    public void setSomeVariable(String someVariable) {
        this.someVariable = someVariable;
    }
}

Nel tuo manifest Android devi dichiarare la classe che implementa android.app.Application (aggiungi l' android:name=".MyApplication"attributo al tag dell'applicazione esistente):

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

Quindi nelle tue attività puoi ottenere e impostare la variabile in questo modo:

// set
((MyApplication) this.getApplication()).setSomeVariable("foo");

// get
String s = ((MyApplication) this.getApplication()).getSomeVariable();

4
ottimo aiuto, l'ho davvero applicato.
d-man

6
Sfortunatamente non funziona per me. Conferma che dopo questo avremo due tag <application> in manifest. Destra? Perché in alcuni punti ho sentito persone dire che dobbiamo aggiungere questo al tag dell'applicazione esistente. Per favore aiuto !!
Adil Malik,

9
@AdilMalik Devi aggiungere il tag android: name al tag dell'applicazione esistente
Marijn

2
Perché non creare semplicemente una classe con campi statici pubblici senza dover accedere a un contesto?
Laserson,

51
Questa non dovrebbe essere una risposta corretta in quanto può portare a comportamenti non previsti e all'NPE a causa della pulizia della memoria. developerphil.com/dont-store-data-in-the-application-object
bakua

43

Puoi usare un Singleton Patterncome questo:

package com.ramps;

public class MyProperties {
private static MyProperties mInstance= null;

public int someValueIWantToKeep;

protected MyProperties(){}

public static synchronized MyProperties getInstance() {
        if(null == mInstance){
            mInstance = new MyProperties();
        }
        return mInstance;
    }
}

Nella tua applicazione puoi accedere al tuo singleton in questo modo:

MyProperties.getInstance().someValueIWantToKeep

28
Che cosa succede se l'attività viene messa in pausa e l'utente avvia un'altra applicazione e durante quella memoria era bassa, ecco perché Android ha rimosso questo oggetto statico quando l'utente ha ripreso l'applicazione e ha trovato questo riferimento statico null ???
d-man il

4
Una statica è inutile tra le attività in processi separati.
ateiob,

3
questo non funzionerà se la tua istanza è raccolta rifiuti. quindi il blocco di codice if (null == mInstance) {mInstance = new MyProperties (); } funzionerà e verrà restituita una nuova istanza, che ripristinerà le proprietà
Lalith B

1
@ Mr.Hyde Singleton non è inutile, è solo che dobbiamo sapere cosa tenere all'interno di Singleton, se manteniamo enormi array di bitmap o alcune raccolte, potrebbe diventare pericoloso. Prendi nota di ciò che tieni all'interno del Singleton.
Lalith B,

1
So di essere un po 'in ritardo, ma per i lettori futuri, possiamo archiviare i valori in SharedPreferences, SQLLite Database o in un file di memoria interna. Tutti questi avranno persistenza dei dati anche se l'applicazione è chiusa.
powernit,

15

Questa variabile globale funziona per il mio progetto:

public class Global {
    public static int ivar1, ivar2;
    public static String svar1, svar2;
    public static int[] myarray1 = new int[10];
}


//  How to use other or many activity
Global.ivar1 = 10;

int i = Global.ivar1;

2
Ma allora come lo passi a più attività?
Zapnologica,

15
Queste statistiche (almeno stringa e array) possono essere annullate dalla VM Android quando l'applicazione è sospesa e il dispositivo ha memoria insufficiente.
Anton,

4
@mahasam non credo che statico dovrebbe essere il modo giusto ... se le sue uniche attività, dovrebbe essere tramite il contesto dell'applicazione. Altrimenti in modo singleton come indicato in altre risposte sopra. static accoppierà fortemente il codice e riduce anche la testabilità
Punith Raj,

14

È possibile utilizzare le preferenze dell'applicazione. Sono accessibili da qualsiasi attività o pezzo di codice fintanto che passi l'oggetto Context e sono privati ​​per l'applicazione che li utilizza, quindi non devi preoccuparti di esporre valori specifici dell'applicazione, a meno che tu non abbia a che fare con routing dispositivi. Tuttavia, è possibile utilizzare schemi di hashing o crittografia per salvare i valori. Inoltre, queste preferenze vengono archiviate da un'applicazione eseguita alla successiva. Ecco alcuni esempi di codice che puoi consultare.


Ho aggiornato il link. Il progetto è stato ospitato su Google Code e, come sappiamo, è stato chiuso. Il link proviene da Github.
r1k0,

8

Esistono diversi modi per ottenere ciò che stai chiedendo.

1.) Estendi la classe dell'applicazione e crea un'istanza del controller e degli oggetti modello lì.

public class FavoriteColorsApplication extends Application {

    private static FavoriteColorsApplication application;
    private FavoriteColorsService service;

    public FavoriteColorsApplication getInstance() {
        return application;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        application = this;
        application.initialize();
    }

    private void initialize() {
        service = new FavoriteColorsService();
    }

    public FavoriteColorsService getService() {
        return service;
    }

}

Quindi puoi chiamare il tuo singleton dal tuo oggetto Applicazione personalizzato in qualsiasi momento:

public class FavoriteColorsActivity extends Activity {

private FavoriteColorsService service = null;
private ArrayAdapter<String> adapter;
private List<String> favoriteColors = new ArrayList<String>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_favorite_colors);

    service = ((FavoriteColorsApplication) getApplication()).getService();
    favoriteColors = service.findAllColors();

    ListView lv = (ListView) findViewById(R.id.favoriteColorsListView);
    adapter = new ArrayAdapter<String>(this, R.layout.favorite_colors_list_item,
            favoriteColors);
    lv.setAdapter(adapter);
}

2.) Puoi avere il tuo controller semplicemente creare un'istanza singleton di se stesso:

public class Controller {
    private static final String TAG = "Controller";
    private static sController sController;
    private Dao mDao;

    private Controller() {
        mDao = new Dao();    
    }

    public static Controller create() {
        if (sController == null) {
            sController = new Controller();
        }
        return sController;
    }
}

Quindi puoi semplicemente chiamare il metodo di creazione da qualsiasi attività o frammento e creerà un nuovo controller se non ne esiste già uno, altrimenti restituirà il controller preesistente.

3.) Infine, c'è un quadro fluido creato in Square che ti fornisce l'iniezione delle dipendenze all'interno di Android. Si chiama Pugnale . Non entrerò nel modo di usarlo qui, ma è molto fluido se hai bisogno di quel genere di cose.

Spero di aver dato abbastanza dettagli su come puoi fare quello che speri.


6

Prova così:

Creare una classe di dati condivisa:

SharedData.java

import android.app.Application;

/**
 * Created by kundan on 6/23/2015.
 */
public class Globals {


    private static Globals instance = new Globals();

    // Getter-Setters
    public static Globals getInstance() {
        return instance;
    }

    public static void setInstance(Globals instance) {
        Globals.instance = instance;
    }

    private String notification_index;


    private Globals() {

    }


    public String getValue() {
        return notification_index;
    }


    public void setValue(String notification_index) {
        this.notification_index = notification_index;
    }



}

Dichiarata / inizializzata un'istanza di classe a livello globale in quelle classi in cui si desidera impostare / ottenere dati (utilizzando questo codice prima del onCreate()metodo): -

Globals sharedData = Globals.getInstance();

Imposta dati:

sharedData.setValue("kundan");

Ottieni dati:

String n = sharedData.getValue();

4

Puoi crearne uno Global Classsimile:

public class GlobalClass extends Application{

    private String name;
    private String email;

    public String getName() {
        return name;
    }

    public void setName(String aName) {
        name = aName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String aEmail) {
        email = aEmail;
    }
}

Quindi definiscilo nel manifest:

<application
    android:name="com.example.globalvariable.GlobalClass" ....

Ora puoi impostare i valori su una variabile globale in questo modo:

final GlobalClass globalVariable = (GlobalClass) getApplicationContext();
globalVariable.setName("Android Example context variable");

Puoi ottenere quei valori in questo modo:

final GlobalClass globalVariable = (GlobalClass) getApplicationContext();
final String name  = globalVariable.getName();

Trova l'esempio completo di questo blog Variabili globali


3
// My Class Global Variables  Save File Global.Java
public class Global {
    public static int myVi; 
    public static String myVs;
}

// How to used on many Activity

Global.myVi = 12;
Global.myVs = "my number";
........
........
........
int i;
int s;
i = Global.myVi;
s = Global.myVs + " is " + Global.myVi;

1
Perché pubblichi due risposte nella stessa domanda? Puoi modificarlo in uno.
Kunu,

2

Ho cercato una risposta simile, ma quelli indicati qui non soddisfano le mie esigenze. Trovo qualcosa che, dal mio punto di vista, è quello che stai cercando. L'unico punto nero possibile è una questione di sicurezza (o forse no) poiché non conosco la sicurezza.

Suggerisco di usare Interface (non c'è bisogno di usare Class con il costruttore e così ...), dal momento che devi solo creare qualcosa come:

public interface ActivityClass {

    public static final String MYSTRING_1 = "STRING";

    public static final int MYINT_1 = 1;

}

Quindi puoi accedere ovunque nelle tue classi utilizzando quanto segue:

int myInt = ActivityClass.MYINT_1;
String myString = ActivityClass.MYSTRING_1;

1

Tecnicamente questo non risponde alla domanda, ma consiglierei di usare il database Room invece di qualsiasi variabile globale. https://developer.android.com/topic/libraries/architecture/room.html Anche se hai "solo" bisogno di archiviare una variabile globale e non è un grosso problema e cosa no, ma usare il database Room è il più elegante , modo nativo e ben supportato di mantenere i valori lungo il ciclo di vita dell'attività. Aiuterà a prevenire molti problemi, in particolare l'integrità dei dati. Comprendo che il database e la variabile globale sono diversi ma si prega di utilizzare Room per motivi di manutenzione del codice, stabilità delle app e integrità dei dati.


1

Utilizzare SharedPreferences per archiviare e recuperare variabili globali.

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String userid = preferences.getString("userid", null);

0

Se possibile, è necessario dichiarare le variabili che è necessario mantenere in vita che non sono state cancellate da Garbage Collector o Scarica dal sistema operativo nel file .so Per farlo, è necessario codificare in C / C ++ e compilare in .so lib file e caricalo nella tua MainActivity.


1
Il codice nativo è un modo doloroso per conservare i dati nella RAM e non farlo meglio delle staticvariabili Java .
Jerry101

Non vedo il punto di questo approccio. Puoi elaborare in questo caso questa è una buona idea?
miva2,

-1
import android.app.Application;

public class Globals extends Application
{
    private static Globals instance = null;
    private static int RecentCompaignID;
    private static int EmailClick;
    private static String LoginPassword;
    static String loginMemberID;
    private static String CompaignName = "";
    private static int listget=0;
    //MailingDetails
    private static String FromEmailadd="";
    private static String FromName="";
    private static String ReplyEmailAdd="";
    private static String CompaignSubject="";
    private static int TempId=0;
    private static int ListIds=0;

    private static String HTMLContent="";
    @Override
    public void onCreate() 
    {
        super.onCreate();
        instance = this;
    }

    public static Globals getInstance()
    {
        return instance;
    }

    public void setRecentCompaignID(int objRecentCompaignID)
    {
        RecentCompaignID = objRecentCompaignID;
    }

    public int getRecentCompaignID() 
    {
        return RecentCompaignID;
    }

    public void setLoginMemberID(String objloginMemberID) 
    {
        loginMemberID = objloginMemberID;
    }

    public String getLoginMemberID() 
    {
        return loginMemberID;
    }

    public void setLoginMemberPassword(String objLoginPassword)
    {
        LoginPassword = objLoginPassword;
    }

    public String getLoginMemberPassword()
    {
        return LoginPassword;
    }

    public void setEmailclick(int id)
    {
        EmailClick = id;
    }

    public int getEmailClick() 
    {
        return EmailClick;
    }
    public void setCompaignName(String objCompaignName)
    {
        CompaignName=objCompaignName;
    }
    public String getCompaignName()
    {
        return CompaignName;
    }
    public void setlistgetvalue(int objlistget)
    {
        listget=objlistget;
    }
    public int getlistvalue()
    {
        return listget;
    }
    public void setCompaignSubject(String objCompaignSubject)
    {
         CompaignSubject=objCompaignSubject;
    }
    public String getCompaignSubject()
    {
        return CompaignSubject;
    }
    public void setHTMLContent(String objHTMLContent)
    {
        HTMLContent=objHTMLContent;
    }
    public String getHTMLContent()
    {
        return HTMLContent;
    }
    public void setListIds(int objListIds)
    {
        ListIds=objListIds;
    }
    public int getListIds()
    {
        return ListIds;
    }
    public void setReplyEmailAdd(String objReplyEmailAdd)
    {
        ReplyEmailAdd=objReplyEmailAdd;
    }
    public String getReplyEmailAdd()
    {
        return ReplyEmailAdd;
    }
    public void setFromName(String objFromName)
    {
        FromName=objFromName;
    }
    public String getFromName()
    {
        return FromName;
    }
    public void setFromEmailadd(String objFromEmailadd)
    {
        FromEmailadd=objFromEmailadd;
    }
    public String getFromEmailadd()
    {
        return FromEmailadd;
    }
}

-5

Facile!!!!

Quelle variabili a cui vuoi accedere come variabili globali, puoi dichiararle come variabili statiche. E ora puoi accedere a quelle variabili usando

classname.variablename;

public class MyProperties {
private static MyProperties mInstance= null;

static int someValueIWantToKeep;

protected MyProperties(){}

public static synchronized MyProperties getInstance(){
    if(null == mInstance){
        mInstance = new MyProperties();
    }
    return mInstance;
}

}

MyProperites.someValueIWantToKeep;

Questo è tutto! ;)


non sono sicuro del motivo per cui è stato votato così tanto in downgrade; confrontandomi con alcune altre risposte potenziate dalla rete, vedo che questo (iirc) utilizza correttamente synchronizedlo statico, getInstance()mentre altri no. valutato di conseguenza.
user2297550
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.