Глобальная переменная Android

293

Как создать глобальную переменную, чтобы сохранить значения в течение всего жизненного цикла приложения, независимо от того, какое действие выполняется.

D-Man
источник
И почему мы должны использовать set и get (ответ Джеффа Гилфельта) ?! Почему мы просто устанавливаем значение непосредственно в переменную? вот так: public volatile static String x; и установить значение: GeneralClass.x = значение;
Dr.jacky

Ответы:

531

Вы можете расширить базовый android.app.Applicationкласс и добавить переменные-члены следующим образом:

public class MyApplication extends Application {

    private String someVariable;

    public String getSomeVariable() {
        return someVariable;
    }

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

В вашем манифесте Android вы должны объявить класс, реализующий android.app.Application (добавьте android:name=".MyApplication"атрибут в существующий тег приложения):

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

Затем в своей деятельности вы можете получить и установить переменную следующим образом:

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

// get
String s = ((MyApplication) this.getApplication()).getSomeVariable();
Джефф Гилфелт
источник
4
огромная помощь, я действительно применяю.
d-man
6
К сожалению, это не работает для меня. Пожалуйста, подтвердите, что после этого у нас будет два тега <application> в манифесте. Правильно? Потому что в некоторых местах я слышал, как люди говорят, что мы должны добавить это в существующий тег приложения. Пожалуйста помоги !!
Адил Малик
9
@AdilMalik Вы должны добавить тег android: name к существующему тегу приложения
Marijn
2
Почему бы просто не создать класс с открытыми статическими полями без необходимости доступа к контексту?
Лазерсон
51
Это не должен быть правильный ответ, так как это может привести к непредсказуемому поведению и NPE из-за очистки памяти. developerphil.com/dont-store-data-in-the-application-object
Баку
43

Вы можете использовать Singleton Patternкак это:

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

В вашем приложении вы можете получить доступ к вашему синглтону следующим образом:

MyProperties.getInstance().someValueIWantToKeep
Рампы
источник
28
Что делать, если активность была приостановлена, и пользователь запустил другое приложение, и во время этой памяти было мало, поэтому Android удалил этот статический объект, когда пользователь возобновил приложение и обнаружил, что эта статическая ссылка пуста ???
d-man
4
Статика бесполезна для разных действий в отдельных процессах.
ateiob
3
это не сработает, если ваш экземпляр является сборщиком мусора. поэтому блок кода if (null == mInstance) {mInstance = new MyProperties (); } будет работать и будет возвращен новый экземпляр, который сбросит свойства
Lalith B
1
@ Mr.Hyde Singleton не бесполезен, просто нам нужно знать, что хранить внутри Singleton. Если мы сохраним огромный массив растровых изображений или некоторые коллекции, это может стать опасным. Имейте в виду, что вы держите в Синглтоне.
Лалит Б,
1
Я знаю, что немного опоздал, но для будущих читателей мы можем хранить значения в SharedPreferences, SQLLite Database или файле внутренней памяти. Все они будут иметь постоянство данных, даже если приложение закрыто.
powernit
15

Эта глобальная переменная работает для моего проекта:

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
источник
2
Но тогда как вы передаете это нескольким действиям?
Запнологика
15
Эта статика (по крайней мере, строка и массив) может быть аннулирована виртуальной машиной Android, когда приложение приостановлено и у устройства недостаточно памяти.
Антон
4
@mahasam Я не думаю, что static должно быть правильным способом ... если это только действия, то это должно происходить через контекст приложения. Еще один способ, как указано в других ответах выше. static сильно связывает код, а также снижает тестируемость
Punith Raj
14

Вы можете использовать настройки приложения. Они доступны из любого действия или фрагмента кода до тех пор, пока вы передаете объект Context, и они являются частными для приложения, которое их использует, поэтому вам не нужно беспокоиться о предоставлении определенных значений приложения, если только вы не имеете дело с маршрутизируемым устройства. Тем не менее, вы можете использовать схемы хеширования или шифрования для сохранения значений. Также эти настройки сохраняются от запуска приложения к следующему. Вот несколько примеров кода, которые вы можете посмотреть.

r1k0
источник
Я обновил ссылку. Проект был размещен на Google Code и, как мы знаем, был закрыт. Ссылка с Github.
r1k0
8

Есть несколько способов добиться того, о чем вы просите.

1.) Расширьте класс приложения и создайте там экземпляр вашего контроллера и модели.

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

}

Затем вы можете в любое время вызвать свой синглтон из пользовательского объекта Application:

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.) Вы можете заставить свой контроллер просто создавать отдельный экземпляр:

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

Затем вы можете просто вызвать метод create из любого действия или фрагмента, и он создаст новый контроллер, если он еще не существует, в противном случае он вернет ранее существовавший контроллер.

3.) Наконец, в Square создана удобная инфраструктура, которая обеспечивает внедрение зависимостей в Android. Это называется Dagger . Я не буду вдаваться в подробности, как использовать это здесь, но это очень удобно, если вам нужны такие вещи.

Надеюсь, я достаточно подробно рассказал о том, как вы можете делать то, на что надеетесь.

Дан Никита
источник
6

Попробуйте вот так:

Создайте общий класс данных:

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



}

Объявлен / инициализирован экземпляр класса глобально в тех классах, где вы хотите установить / получить данные (используя этот код перед onCreate()методом): -

Globals sharedData = Globals.getInstance();

Установить данные:

sharedData.setValue("kundan");

Получить данные:

String n = sharedData.getValue();
Кумар Кундан
источник
4

Вы можете создать Global Classтак:

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

Затем определите это в манифесте:

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

Теперь вы можете установить значения для глобальной переменной следующим образом:

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

Вы можете получить эти значения следующим образом:

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

Пожалуйста, найдите полный пример из этого блога Глобальные переменные

san88
источник
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
источник
1
Почему вы публикуете два ответа на один и тот же вопрос? Вы можете отредактировать это к одному.
Куну
2

Я проверил на аналогичный ответ, но приведенные здесь не соответствуют моим потребностям. Я нахожу то, что, с моей точки зрения, это то, что вы ищете. Единственная возможная черная точка - это вопрос безопасности (а может и нет), так как я не знаю о безопасности.

Я предлагаю использовать интерфейс (не нужно использовать Class с конструктором и т. Д.), Так как вам нужно только создать что-то вроде:

public interface ActivityClass {

    public static final String MYSTRING_1 = "STRING";

    public static final int MYINT_1 = 1;

}

Затем вы можете получить доступ ко всем в ваших классах, используя следующее:

int myInt = ActivityClass.MYINT_1;
String myString = ActivityClass.MYSTRING_1;
Александр
источник
1

Технически это не отвечает на вопрос, но я бы рекомендовал использовать базу данных Room вместо любой глобальной переменной. https://developer.android.com/topic/libraries/architecture/room.html Даже если вам «просто» нужно хранить глобальную переменную, и это не сложно, а что нет, но использование базы данных Room является наиболее элегантным , родной и хорошо поддерживаемый способ сохранения ценностей в течение жизненного цикла деятельности. Это поможет предотвратить многие проблемы, особенно целостность данных. Я понимаю, что база данных и глобальные переменные разные, но, пожалуйста, используйте Room для обслуживания кода, стабильности приложения и целостности данных.

hexicle
источник
1

Используйте SharedPreferences для хранения и извлечения глобальных переменных.

SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String userid = preferences.getString("userid", null);
Коен Дамен
источник
0

Если возможно, вы должны объявить переменные, которые вам нужны, чтобы они оставались в живых, которые не были очищены сборщиком мусора или выгружены ОС в файл .so загрузить его в свой MainActivity.

Чан Хуу Фуок
источник
1
Нативный код - это болезненный способ хранения данных в оперативной памяти, и он не лучше, чем staticпеременные Java .
Jerry101
Я не вижу смысла в этом подходе. Можете ли вы уточнить, в каком случае это хорошая идея?
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;
    }
}
user2054528
источник
-5

Легко!!!!

Те переменные, к которым вы хотите обращаться как к глобальным переменным, вы можете объявить как статические переменные. И теперь вы можете получить доступ к этим переменным с помощью

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;

Это оно! ;)

Динеш Падвал
источник
не уверен, почему за него так много проголосовали; Сравнивая с некоторыми другими ответами по нетто-голосованию, я вижу, что это правильно (iirc) использует synchronizedстатическое, getInstance()а другие нет. проголосовал соответственно.
user2297550