如何在Android中声明全局变量?

时间:2009-04-02 01:54:30

标签: android singleton global-variables state

我正在创建一个需要登录的应用程序。我创建了主要和登录活动。

在主要活动onCreate方法中,我添加了以下条件:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ...

    loadSettings();
    if(strSessionString == null)
    {
        login();
    }
    ...
}

登录表单终止时执行的onActivityResult方法如下所示:

@Override
public void onActivityResult(int requestCode,
                             int resultCode,
                             Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode)
    {
        case(SHOW_SUBACTICITY_LOGIN):
        {
            if(resultCode == Activity.RESULT_OK)
            {

                strSessionString = data.getStringExtra(Login.SESSIONSTRING);
                connectionAvailable = true;
                strUsername = data.getStringExtra(Login.USERNAME);
            }
        }
    }

问题是登录表单有时会出现两次(login()方法被调用两次),当手机键盘滑动时,再次出现登录表单,我猜问题是变量strSessionString

有没有人知道如何设置变量global以避免在用户成功通过身份验证后出现登录表单?

16 个答案:

答案 0 :(得分:947)

答案 1 :(得分:153)

创建此子类

public class MyApp extends Application {
  String foo;
}

在AndroidManifest.xml中添加android:name

示例

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

答案 2 :(得分:142)

Soonil建议保持申请状态的方式很好,但它有一个弱点 - 有些情况下操作系统会杀死整个申请流程。以下是有关此文档的文档 - Processes and lifecycles

考虑一个案例 - 你的应用程序进入后台,因为有人在给你打电话(手机应用程序现在在前台)。在这种情况下&amp;&amp;在某些其他条件下(检查上面的链接是否可能),操作系统可能会终止您的应用程序进程,包括Application子类实例。结果,国家失去了。当您稍后返回应用程序时,操作系统将恢复其活动堆栈和Application子类实例,但myState字段将为null

AFAIK,保证国家安全的唯一方法是使用任何类型的持久状态,例如:使用私有应用程序文件或SharedPrefernces(它最终使用私有内容文件系统中的应用程序文件)。

答案 3 :(得分:26)

只是一张便条..

添加:

android:name=".Globals"

或您将现有 <application>标记命名为子类的任何内容。我一直试图在清单中添加另一个<application>标记,并会得到一个例外。

答案 4 :(得分:13)

我也找不到如何指定应用程序标签,但经过大量的Google搜索后,从清单文件docs中可以看出:除了应用程序节中的默认图标和标签外,还使用了android:name。

机器人:名称 为应用程序实现的Application子类的完全限定名称。启动应用程序进程时,将在应用程序的任何组件之前实例化此类。

子类是可选的;大多数应用程序不需要一个。在没有子类的情况下,Android使用基本Application类的实例。

答案 5 :(得分:13)

如何确保收集具有此类全局结构的本机内存?

活动有一个onPause/onDestroy()方法,在销毁时调用,但Application类没有等效方法。建议使用什么机制来确保在应用程序被终止或任务堆栈放在后台时对全局结构(特别是包含对本机内存的引用的结构)进行适当的垃圾收集?

答案 6 :(得分:5)

您需要定义一个如下所示的应用程序名称:

<application
  android:name="ApplicationName" android:icon="@drawable/icon">
</application>

答案 7 :(得分:4)

如果某些变量存储在sqlite中,您必须在应用中的大多数活动中使用它们。 应用程序可能是实现它的最佳方式。 在应用程序启动时从数据库中查询变量并将其存储在字段中。 然后,您可以在活动中使用这些变量。

所以找到正确的方法,没有最好的办法。

答案 8 :(得分:4)

就像上面讨论的那样OS可以在没有任何通知的情况下终止APPLICATION(没有onDestroy事件),所以没有办法保存这些全局变量。

SharedPreferences可能是一个解决方案,除非你有COMPLEX STRUCTURED变量(在我的例子中,我有整数数组来存储用户已经处理过的ID)。 SharedPreferences的问题在于,每次需要值时都很难存储和检索这些结构。

在我的情况下,我有一个后台服务,所以我可以将这些变量移到那里,因为服务有onDestroy事件,我可以轻松保存这些值。

答案 9 :(得分:3)

您可以使用静态字段来存储此类状态。或者将它放到资源Bundle上并从那里恢复onCreate(Bundle savedInstanceState)。只需确保您完全了解Android应用管理生命周期(例如,为什么在键盘方向更改时调用login())。

答案 10 :(得分:2)

不要在清单文件中使用其他<application>标记。只需对现有<application>代码进行一次更改,将此行android:name=".ApplicationName"添加到其中,{ {1}}将是您要创建的子类的名称(用于存储全局)。

所以,最后清单文件中的 ONE AND ONLY ApplicationName标记应该如下所示: -

<application>

答案 11 :(得分:1)

您可以使用Intents,Sqlite或共享首选项。对于媒体存储,例如文档,照片和视频,您可以改为创建新文件。

答案 12 :(得分:0)

class GlobaleVariableDemo extends Application {

    private String myGlobalState;

    public String getGlobalState(){
     return myGlobalState;
    }
    public void setGlobalState(String s){
     myGlobalState = s;
    }
}

class Demo extends Activity {

@Override
public void onCreate(Bundle b){
    ...
    GlobaleVariableDemo appState = ((GlobaleVariableDemo)getApplicationContext());
    String state = appState.getGlobalState();
    ...
    }
}

答案 13 :(得分:0)

在恢复之前调用活动结果。因此,将登录检查移至恢复状态,一旦secomd活动返回肯定结果,您的第二次登录就会被阻止。每次都会调用简历,因此不必担心第一次没有调用它。

答案 14 :(得分:0)

BARACUS框架也使用了子类化的方法。从我的角度来看子类化应用程序旨在与Android的生命周期一起工作;这是任何应用程序容器的功能。我没有使用全局变量,而是将bean注册到这个上下文中,让它们被注入任何可由上下文管理的类中。每个注入的bean实例实际上都是一个单例。

See this example for details

如果你可以拥有更多的东西,为什么手动工作?

答案 15 :(得分:0)

您可以创建一个扩展Application类的类,然后将您的变量声明为该类的字段并为其提供getter方法。

public class MyApplication extends Application {
    private String str = "My String";

    synchronized public String getMyString {
        return str;
    }
}

然后要在您的Activity中访问该变量,请使用:

MyApplication application = (MyApplication) getApplication();
String myVar = application.getMyString();