【问题标题】:Android global variable安卓全局变量
【发布时间】:2010-12-29 00:22:33
【问题描述】:

如何在应用程序的生命周期内创建全局变量保持值,而不管运行哪个活动。

【问题讨论】:

  • 为什么我们应该使用 set 和 get(Jeff Gilfelt 的 asnwer)?!为什么我们只是将值直接设置为变量?像这样: public volatile static String x;并设置值:GeneralClass.x = value;

标签: android global-variables


【解决方案1】:

您可以像这样使用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

【讨论】:

  • 如果活动暂停并且用户启动了另一个应用程序并且在那个内存不足期间这就是为什么android在用户恢复应用程序并发现这个静态引用为空时删除了这个静态对象并发现这个静态引用??
  • 静态在不同进程中的活动中是无用的。
  • 如果您的实例被垃圾回收,这将不起作用。所以代码块 if(null == mInstance){ mInstance = new MyProperties(); } 将起作用并返回新实例,这将重置属性
  • @Mr.Hyde Singleton 并不是没有用的,它只是我们需要知道在 Singleton 中保留什么,如果我们保留巨大的位图数组或一些集合,那么它可能会变得很危险。记下您在 Singleton 中保留的内容。
  • 我知道我来晚了,但对于未来的读者,我们可以将值存储在 SharedPreferences、SQLLite 数据库或内部内存文件中。即使应用程序关闭,这些都将具有数据持久性。
【解决方案2】:

您可以扩展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();

【讨论】:

  • 很棒的帮助,我真的申请了。
  • 不幸的是,它对我不起作用。请确认在此之后我们将在清单中有两个 标记。正确的?因为在某些地方我听到人们说我们必须将它添加到现有的应用程序标签中。请帮忙!!
  • @AdilMalik 您必须将 android:name 标签添加到现有的应用程序标签
  • 为什么不直接创建一个具有公共静态字段的类而不需要访问上下文?
  • 这不应该是正确的答案,因为它可能导致不可预测的行为和由于内存清理而导致的 NPE。 developerphil.com/dont-store-data-in-the-application-object
【解决方案3】:

您可以使用应用程序首选项。只要您传递 Context 对象,它们就可以从任何活动或代码段访问,并且它们对于使用它们的应用程序是私有的,因此您无需担心暴露应用程序特定的值,除非您处理路由设备。即便如此,您也可以使用散列或加密方案来保存值。此外,这些首选项存储从应用程序运行到下一个。 Here 是一些代码示例,你可以看看。

【讨论】:

  • 我已经更新了链接。项目托管在 Google Code 上,我们知道该项目已关闭。链接来自 Github。
【解决方案4】:

简单!!!!

那些你想作为全局变量访问的变量,你可以将它们声明为静态变量。现在,您可以使用

类名.变量名;

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)在静态getInstance() 上使用synchronized,而其他人则没有。相应地投了赞成票。
  • 因为它是从上面的答案复制而来的。
【解决方案5】:
// 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;

【讨论】:

  • 为什么您在同一个问题中发布两个答案?您可以将其编辑为一个。
【解决方案6】:

这个全局变量适用于我的项目:

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;

【讨论】:

  • 但是如何将它传递给多个活动?
  • 当应用程序挂起并且设备内存不足时,这些静态数据(至少是字符串和数组)可能会被 android VM 清空。
  • @mahasam 我不认为静态应该是正确的方式......如果它唯一的活动,它应该是通过应用程序上下文。其他上面其他答案中给出的单例方式。 static 会强耦合代码,也会降低可测试性
【解决方案7】:
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;
    }
}

【讨论】:

    【解决方案8】:

    如果可能,您应该在文件 .so 中声明您需要保持活动状态的变量,这些变量尚未被垃圾收集器清除或被操作系统卸载 为此,您必须使用 C/C++ 编写代码并编译为 .so lib 文件并将其加载到您的 MainActivity 中。

    【讨论】:

    • 原生代码是一种将数据保存在 RAM 中的痛苦方式,而且这样做并不比 Java static 变量好。
    • 我不明白这种方法的意义。您能否详细说明在哪种情况下这是个好主意?
    【解决方案9】:

    有几种不同的方法可以实现您的要求。

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

    然后您可以从任何 Activity 或 Fragment 调用 create 方法,如果控制器不存在,它将创建一个新控制器,否则它将返回先前存在的控制器。

    3.) 最后,Square 创建了一个精巧的框架,可以在 Android 中为您提供依赖注入。它被称为Dagger。我不会在这里详细介绍如何使用它,但是如果您需要那种东西,它会非常巧妙。

    我希望我提供了足够的详细信息来说明如何做你希望做的事情。

    【讨论】:

      【解决方案10】:

      您可以像这样创建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;
          }
      }
      

      然后在manifest中定义:

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

      请从这个博客中找到完整的例子 Global Variables

      【讨论】:

      • 如果我在活动中写“final GlobalClass globalVariable = (GlobalClass) getApplicationContext();”获取无法转换为 application.Global 的异常。
      【解决方案11】:

      试试这样:

      创建共享数据类:

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

      【讨论】:

        【解决方案12】:

        我检查了类似的答案,但这里给出的答案不符合我的需要。 从我的角度来看,我找到了您正在寻找的东西。唯一可能的黑点是安全问题(或者可能不是),因为我不了解安全性。

        我建议使用接口(不需要使用带有构造函数的类等等......),因为你只需要创建类似的东西:

        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;
        

        【讨论】:

          【解决方案13】:

          从技术上讲,这并不能回答问题,但我建议使用 Room 数据库而不是任何全局变量。 https://developer.android.com/topic/libraries/architecture/room.html 即使您“只”需要存储一个全局变量,这没什么大不了的,但使用 Room 数据库是在活动的生命周期中保持值的最优雅、原生和得到良好支持的方式。 它将有助于防止许多问题,尤其是数据的完整性。 我了解数据库和全局变量不同,但出于代码维护、应用程序稳定性和数据完整性的考虑,请使用 Room。

          【讨论】:

            【解决方案14】:

            使用 SharedPreferences 存储和检索全局变量。

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

            【讨论】:

            • 考虑到其他应用程序的可靠性、隐私性和不可访问性,这应该被赞成。
            猜你喜欢
            • 2015-09-19
            • 2021-03-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-03-07
            • 2015-07-07
            相关资源
            最近更新 更多