Variable global de Android

293

¿Cómo puedo crear variables globales para mantener los valores alrededor del ciclo de vida de la aplicación, independientemente de la actividad que se esté ejecutando?

d-man
fuente
¿Y por qué deberíamos usar set and get (la respuesta de Jeff Gilfelt) ?! ¿Por qué simplemente establecemos el valor directamente en variable? así: Cadena estática pública volátil x; y para establecer el valor: GeneralClass.x = valor;
Dr.jacky

Respuestas:

531

Puede extender la android.app.Applicationclase base y agregar variables miembro de la siguiente manera:

public class MyApplication extends Application {

    private String someVariable;

    public String getSomeVariable() {
        return someVariable;
    }

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

En su manifiesto de Android, debe declarar la clase que implementa android.app.Application (agregue el android:name=".MyApplication"atributo a la etiqueta de aplicación existente):

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

Luego, en sus actividades, puede obtener y establecer la variable de la siguiente manera:

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

// get
String s = ((MyApplication) this.getApplication()).getSomeVariable();
Jeff Gilfelt
fuente
44
Ayuda increíble, realmente lo solicito.
d-man el
66
Lamentablemente no me funciona. Confirme que después de esto tendremos dos etiquetas <application> en manifiesto. ¿Correcto? Porque en algunos lugares escuché a personas decir que tenemos que agregar esto a la etiqueta de la aplicación existente. Por favor ayuda !!
Adil Malik
99
@AdilMalik Debe agregar la etiqueta android: name a la etiqueta de la aplicación existente
Marijn
2
¿Por qué no simplemente crear una clase con campos públicos estáticos sin necesidad de acceder a un contexto?
Laserson
51
Esta no debería ser la respuesta correcta, ya que puede conducir a un comportamiento imprevisto y a NPE debido a la limpieza de la memoria. developerphil.com/dont-store-data-in-the-application-object
bakua
43

Puedes usar un Singleton Patterncomo este:

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;
    }
}

En su aplicación puede acceder a su singleton de esta manera:

MyProperties.getInstance().someValueIWantToKeep
Rampas
fuente
28
¿Qué pasaría si la actividad se detuviera y el usuario iniciara otra aplicación y durante esa memoria fuera baja, por eso Android eliminó este objeto estático cuando el usuario reanudó la aplicación y encontró esta referencia estática nula?
d-man
44
Una estática es inútil en todas las actividades en procesos separados.
ateiob
3
esto no funcionará si su instancia es recolección de basura. entonces el bloque de código if (null == mInstance) {mInstance = new MyProperties (); } funcionará y se devolverá una nueva instancia, que restablecerá las propiedades
Lalith B
1
@ Mr.Hyde Singleton no es inútil, es solo que necesitamos saber qué guardar dentro de Singleton, si mantenemos enormes conjuntos de mapas de bits o algunas colecciones, entonces puede ser peligroso. Tenga en cuenta lo que guarda dentro del Singleton.
Lalith B
1
Sé que llego un poco tarde, pero para futuros lectores, podemos almacenar valores en SharedPreferences, SQLLite Database o An Internal memory file. Todos estos tendrán persistencia de datos incluso si la aplicación está cerrada.
powernit
15

Esta variable global funciona para mi proyecto:

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;
mahasam
fuente
2
Pero entonces, ¿cómo lo pasas a múltiples actividades?
Zapnologica
15
La VM de Android puede anular estas estadísticas (al menos cadena y matriz) cuando la aplicación se suspende y el dispositivo tiene poca memoria.
Anton
44
@mahasam, no creo que la estática deba ser la forma correcta ... si solo son actividades, debería ser a través del contexto de la Aplicación. De lo contrario, como se indica en otras respuestas anteriores. static está fuertemente acoplado al código, y también reduce la
capacidad de prueba
14

Podrías usar las preferencias de la aplicación. Son accesibles desde cualquier actividad o fragmento de código siempre que pase el objeto Context, y son privados para la aplicación que los utiliza, por lo que no debe preocuparse por exponer los valores específicos de la aplicación, a menos que trate con enrutado dispositivos. Aun así, puede usar esquemas de cifrado o hash para guardar los valores. Además, estas preferencias se almacenan desde una aplicación ejecutada hasta la siguiente. Aquí hay algunos ejemplos de código que puede ver.

r1k0
fuente
He actualizado el enlace. El proyecto se alojó en Google Code y, como sabemos, se cerró. El enlace es de Github.
r1k0
8

Hay algunas maneras diferentes en que puede lograr lo que está pidiendo.

1.) Extienda la clase de aplicación e instancia su controlador y objetos de modelo allí.

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;
    }

}

Luego puede llamar a su singleton desde su objeto de Aplicación personalizada en cualquier 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.) Puede hacer que su controlador simplemente cree una instancia singleton de sí mismo:

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;
    }
}

Luego puede llamar al método de creación desde cualquier Actividad o Fragmento y creará un nuevo controlador si aún no existe, de lo contrario devolverá el controlador preexistente.

3.) Finalmente, hay un marco elegante creado en Square que le proporciona inyección de dependencia dentro de Android. Se llama Daga . No explicaré cómo usarlo aquí, pero es muy hábil si necesitas ese tipo de cosas.

Espero haber dado suficientes detalles sobre cómo puedes hacer lo que esperas.

Dan Mikita
fuente
6

Intenta así:

Crear una clase de datos compartidos:

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;
    }



}

Declarado / Iniciado una instancia de clase globalmente en aquellas clases donde desea establecer / obtener datos (utilizando este código antes del onCreate()método): -

Globals sharedData = Globals.getInstance();

Establecer datos:

sharedData.setValue("kundan");

Obtener datos:

String n = sharedData.getValue();
kumar kundan
fuente
4

Puede crear un Global Classcomo este:

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;
    }
}

Luego defínalo en el manifiesto:

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

Ahora puede establecer valores en una variable global como esta:

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

Puede obtener esos valores como este:

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

Encuentre el ejemplo completo de este blog Variables globales

san88
fuente
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;
mahasam
fuente
1
¿Por qué publica dos respuestas en la misma pregunta? Puedes editarlo en uno.
Kunu
2

Verifiqué una respuesta similar, pero las que figuran aquí no se ajustan a mis necesidades. Encuentro algo que, desde mi punto de vista, es lo que estás buscando. El único punto negro posible es un asunto de seguridad (o tal vez no) ya que no sé sobre seguridad.

Sugiero usar Interface (no es necesario usar Class con constructor y así ...), ya que solo tiene que crear algo como:

public interface ActivityClass {

    public static final String MYSTRING_1 = "STRING";

    public static final int MYINT_1 = 1;

}

Luego puede acceder a todas partes dentro de sus clases utilizando lo siguiente:

int myInt = ActivityClass.MYINT_1;
String myString = ActivityClass.MYSTRING_1;
Alexandre
fuente
1

Técnicamente, esto no responde la pregunta, pero recomendaría usar la base de datos Room en lugar de cualquier variable global. https://developer.android.com/topic/libraries/architecture/room.html Incluso si 'solo' necesita almacenar una variable global y no es gran cosa y qué no, pero usar la base de datos de Room es lo más elegante , forma nativa y bien apoyada de mantener valores en torno al ciclo de vida de la actividad. Ayudará a prevenir muchos problemas, especialmente la integridad de los datos. Entiendo que la base de datos y la variable global son diferentes, pero use Room para mantener el código, la estabilidad de la aplicación y la integridad de los datos.

hexicle
fuente
1

Use SharedPreferences para almacenar y recuperar variables globales.

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

Si es posible, debe declarar las variables que necesita para mantener vivas que Garbage Collector no haya borrado o Descargar mediante OS en el archivo .so Para hacerlo, debe codificar por C / C ++ y compilar en el archivo .so lib y cárguelo en su actividad principal.

Tran Huu Phuoc
fuente
1
El código nativo es una forma dolorosa de mantener los datos en la RAM, y no lo hace mejor que las staticvariables de Java .
Jerry101
No veo el punto de este enfoque. ¿Puedes explicar en qué caso es una buena 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;
    }
}
usuario2054528
fuente
-5

¡¡¡¡Fácil!!!!

A las variables a las que desea acceder como variable global, puede declararlas como variables estáticas. Y ahora, puede acceder a esas variables utilizando

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;

¡Eso es! ;)

Dinesh Padwal
fuente
no estoy seguro de por qué fue rechazado tanto; en comparación con algunas otras respuestas con voto de voto positivo, veo que esto se usa correctamente (iirc) synchronizeden la estática, getInstance()mientras que otros no. votado en consecuencia.
user2297550