ตัวแปรโกลบอลของ Android


293

ฉันจะสร้างตัวแปรส่วนกลางเก็บค่าไว้รอบวงจรชีวิตของแอปพลิเคชันได้อย่างไรโดยไม่คำนึงถึงกิจกรรมที่กำลังทำงานอยู่


และทำไมเราควรใช้ set และ get (asnwer ของ Jeff Gilfelt)?! ทำไมเราแค่ตั้งค่าโดยตรงกับตัวแปร? ดังนี้: สตริงคงที่ระเหยแบบสาธารณะ x; และเพื่อตั้งค่า: GeneralClass.x = value;
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.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> สองรายการในรายการ ขวา? เพราะในบางสถานที่ฉันได้ยินคนพูดว่าเราต้องเพิ่มสิ่งนี้ลงในแท็กแอปพลิเคชันที่มีอยู่ กรุณาช่วย !!
Adil Malik

9
@AdilMalik คุณต้องเพิ่ม android: แท็กชื่อในแท็กแอปพลิเคชันที่มีอยู่
Marijn

2
ทำไมไม่เพียงแค่สร้างคลาสที่มีสแตติกสาธารณะโดยไม่จำเป็นต้องเข้าถึงบริบท?
Laserson

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
จะเกิดอะไรขึ้นถ้ากิจกรรมที่หยุดชั่วคราวและผู้ใช้เริ่มต้นแอปพลิเคชันอื่นและในระหว่างที่ memeory นั้นต่ำนั่นเป็นสาเหตุที่ android ลบวัตถุคงที่นี้เมื่อผู้ใช้กลับมาใช้งานแอปพลิเคชันอีกครั้ง
d-man

4
คงที่ไม่มีประโยชน์ในกิจกรรมในกระบวนการที่แยกต่างหาก
ateiob

3
สิ่งนี้จะไม่ทำงานหากอินสแตนซ์ของคุณเก็บรวบรวมขยะ ดังนั้นบล็อกของรหัสถ้า (null == mInstance) {mInstance = new MyProperties (); } จะทำงานและอินสแตนซ์ใหม่จะถูกส่งคืนซึ่งจะรีเซ็ตคุณสมบัติ
Lalith B

1
@ Mr.Hyde Singleton ไม่ได้ไร้ประโยชน์มันแค่ว่าเราต้องรู้ว่าอะไรที่จะเก็บไว้ใน Singleton ถ้าเราเก็บอาร์เรย์ของบิตแมปขนาดใหญ่หรือคอลเลกชันบางอย่างมันอาจเป็นอันตรายได้ จดบันทึกสิ่งที่คุณเก็บไว้ในซิงเกิล
Lalith B

1
ฉันรู้ว่าฉันช้าไปหน่อย แต่สำหรับผู้อ่านในอนาคตเราสามารถจัดเก็บค่าใน SharedPreferences, ฐานข้อมูล SQLLite หรือไฟล์หน่วยความจำภายใน สิ่งเหล่านี้ทั้งหมดจะมีข้อมูลคงอยู่แม้ว่าแอปพลิเคชันจะถูกปิด
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
สถิตศาสตร์เหล่านี้ (อย่างน้อยสตริงและอาร์เรย์) อาจถูกลบโดย android VM เมื่อแอปพลิเคชันถูกระงับและอุปกรณ์มีหน่วยความจำเหลือน้อย
Anton

4
@mahasam ฉันไม่คิดว่าคงเป็นวิธีที่ถูกต้อง ... ถ้าเป็นเพียงกิจกรรมมันควรจะผ่านบริบทของแอปพลิเคชัน เป็นวิธีเดียวที่ได้รับในคำตอบอื่น ๆ ข้างต้น คงที่จะจับคู่รหัสอย่างมากและยังช่วยลดการทดสอบ
Punith Raj

14

คุณสามารถใช้การตั้งค่าแอปพลิเคชัน พวกเขาสามารถเข้าถึงได้จากกิจกรรมหรือชิ้นส่วนของรหัสใด ๆ ตราบใดที่คุณส่งผ่านวัตถุบริบทและพวกเขาเป็นส่วนตัวกับแอปพลิเคชันที่ใช้พวกเขาดังนั้นคุณไม่จำเป็นต้องกังวลเกี่ยวกับการเปิดเผยค่าเฉพาะแอปพลิเคชัน อุปกรณ์ ถึงกระนั้นคุณสามารถใช้รูปแบบการแฮชหรือการเข้ารหัสเพื่อบันทึกค่า นอกจากนี้การตั้งค่าเหล่านี้จะถูกจัดเก็บจากแอปพลิเคชันที่เรียกใช้ไปยังถัดไป นี่คือตัวอย่างโค้ดที่คุณสามารถดูได้


ฉันอัพเดทลิงค์แล้ว โปรเจ็กต์ถูกโฮสต์บน 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;
    }
}

จากนั้นคุณสามารถเรียกใช้เมธอด create จากกิจกรรมหรือแฟรกเมนต์ใดก็ได้และมันจะสร้างตัวควบคุมใหม่หากไม่มีอยู่แล้วมิฉะนั้นจะส่งคืนคอนโทรลเลอร์ที่มีอยู่ก่อนหน้า

3. ) ในที่สุดก็มีกรอบการทำงานที่เรียบเนียนที่สร้างขึ้นที่ Square ซึ่งจะช่วยให้คุณสามารถฉีดระบบ 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
ทำไมคุณโพสต์สองคำตอบในคำถามเดียวกัน คุณสามารถแก้ไขเป็นหนึ่ง
Kunu

2

ฉันตรวจสอบคำตอบที่คล้ายกัน แต่คำตอบที่ระบุไม่ตรงกับความต้องการของฉัน ฉันพบบางสิ่งที่จากมุมมองของฉันคือสิ่งที่คุณกำลังมองหา จุดดำเดียวที่เป็นไปได้คือเรื่องความปลอดภัย (หรืออาจจะไม่ใช่) เพราะฉันไม่รู้เรื่องความปลอดภัย

ฉันขอแนะนำให้ใช้อินเทอร์เฟซ (ไม่จำเป็นต้องใช้คลาสกับตัวสร้างและอื่น ๆ ... ) เนื่องจากคุณต้องสร้างบางสิ่งเช่น:

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/l ไลบรารี/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
รหัสเนทีฟเป็นวิธีที่เจ็บปวดในการเก็บข้อมูลใน RAM และทำได้ดีกว่า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;

แค่นั้นแหละ! ;)


ไม่แน่ใจว่าทำไมมันลดลงมาก เมื่อเปรียบเทียบกับคำตอบ net-upvote อื่น ๆ ฉันเห็นว่าสิ่งนี้ถูกต้อง (iirc) ใช้synchronizedกับสแตติกgetInstance()ขณะที่คนอื่นไม่ทำ upvoted ตาม
2297550
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.