Android глобальна змінна


293

Як я можу створити глобальну змінну, щоб залишитись значеннями протягом життєвого циклу програми незалежно від того, яка діяльність виконується.


І чому ми повинні використовувати set і дістатись (підпис Джеффа Гілфельта) ?! Чому ми просто встановлюємо значення безпосередньо на змінну? ось так: загальнодоступний статичний струнний струн і встановити значення: 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
bakua

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
Що робити, якщо активність призупинилася, і користувач запустив іншу програму, і під час цієї меморії було низько, чому андроїд видалив цей статичний об'єкт, коли користувач відновив додаток і знайшов цю статичну посилання нульовою ???
d-man

4
Статична статистика марна в діяльності в окремих процесах.
ateiob

3
ця робота не буде, якщо ваш екземпляр збирає сміття. тому блок коду if (null == mInstance) {mInstance = new MyProperties (); } буде працювати, і буде повернуто новий екземпляр, який скине властивості
Lalith B

1
@ Mr.Hyde Сінглтон не марний, це просто те, що нам потрібно знати, що зберігати всередині Singleton, якщо ми збережемо величезний масив растрових зображень або деякі колекції, то це може стати небезпечним. Зауважте, що ви тримаєте всередині Singleton.
Lalith B

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;

2
Але як тоді ви передаєте це в кілька заходів?
Zapnologica

15
Ці статики (принаймні рядок і масив) можуть анулювати андроїд VM, коли програма призупинена, а пристрій має мало пам'яті.
Антон

4
@mahasam я не думаю, що статичне має бути правильним способом ... якщо це лише його діяльність, це має бути через контекст програми. Ще один спосіб, як зазначено в інших відповідях вище. static сильно з'єднає код, а також знизить доказовість
Punith Raj,

14

Ви можете використовувати налаштування програми. Вони доступні з будь-якої активності або фрагмента коду, поки ви переходите на об'єкт Context, і вони є приватними для програми, яка їх використовує, тому вам не потрібно турбуватися про викриття конкретних значень програми, якщо ви не маєте справу з маршрутизованими пристрої. Незважаючи на це, ви можете використовувати схеми хешування або шифрування для збереження значень. Також ці налаштування зберігаються від запуску програми до наступного. Ось кілька прикладів коду, які ви можете подивитися.


Я оновив посилання. Проект розміщувався в 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;
    }

}

Тоді ви можете в будь-який час зателефонувати вашому одиночному користувачеві зі свого спеціального об’єкта програми:

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

Тоді ви можете просто викликати метод створення з будь-якої діяльності або фрагмента, і він створить новий контролер, якщо його ще не існує, інакше він поверне вже існуючий контролер.

3.) Нарешті, на Площі створений гладкий фреймворк, який забезпечує введення залежності в Android. Його називають кинджалом . Я не буду розбиратися в тому, як його використовувати тут, але це дуже гладко, якщо вам потрібна така річ.

Я сподіваюся, що я детально розповів про те, як ти можеш робити те, на що ти сподівається.


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();

Знайдіть повний приклад з цього блогу « Глобальні змінні»


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
Чому ви розміщуєте дві відповіді в одному запитанні? Ви можете відредагувати його до одного.
Куну

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

Технічно це не відповідає на питання, але я б рекомендував використовувати базу даних кімнат замість будь-якої глобальної змінної. https://developer.android.com/topic/libraries/architecture/room.html Навіть якщо вам потрібно "лише" зберігати глобальну змінну, і це вже не так, і що ні, але використання бази даних Room - це найелегантніше , рідний і добре підтримуваний спосіб збереження цінностей протягом життєвого циклу діяльності. Це допоможе запобігти багатьом проблемам, особливо цілісності даних. Я розумію, що база даних та глобальна змінна є різними, але, будь ласка, використовуйте номер для підтримки коду, стабільності програми та цілісності даних.


1

Використовуйте SharedPreferences для зберігання та отримання глобальних змінних.

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

0

Якщо це можливо, вам слід оголосити змінні, які вам потрібно зберегти в живих, які не були зрозумілими Garbage Collector або Unload by OS у файл. Тому для цього потрібно ввести код C / C ++ і компілювати в файл .so lib і завантажте його у свою 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;
    }
}

-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()тоді як інші - ні. відповідно.
користувач2297550
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.