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

在主活动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。

有人知道如何设置变量全局,以避免登录表单出现后,用户已经成功验证?


当前回答

在活动结果之前在简历上被调用。所以移动你的登录检查到恢复和你的第二次登录可以被阻止,一旦第二个活动已经返回积极的结果。On简历每次都会被调用,所以不用担心第一次没有被调用。

其他回答

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

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

我在09年写了这个答案,当时Android还相对较新,在Android开发中还有许多不成熟的领域。我在这篇文章的底部添加了一个很长的附录,解决了一些批评,并详细说明了我在使用单例而不是应用程序子类化方面的哲学分歧。请自行承担阅读风险。

最初的回答:

您遇到的更普遍的问题是如何跨多个activity和应用程序的所有部分保存状态。静态变量(例如,单例变量)是一种常见的Java实现方式。然而,我发现在Android中更优雅的方式是将你的状态与应用程序上下文关联起来。

如您所知,每个活动也是一个上下文,从最广泛的意义上讲,上下文是关于其执行环境的信息。你的应用程序也有一个上下文,Android保证它在你的应用程序中作为一个单独的实例存在。

方法是创建你自己的android.app的子类。Application,然后在清单中的Application标记中指定该类。现在,Android将自动创建该类的实例,并使其可用于整个应用程序。您可以使用context . getapplicationcontext()方法从任何上下文访问它(Activity还提供了一个方法getApplication(),具有完全相同的效果)。下面是一个极其简化的示例,需要注意以下事项:

class MyApp extends Application {

  private String myState;

  public String getState(){
    return myState;
  }
  public void setState(String s){
    myState = s;
  }
}

class Blah extends Activity {

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

这本质上与使用静态变量或单例具有相同的效果,但可以很好地集成到现有的Android框架中。注意,这将不能跨进程工作(如果你的应用程序是一个罕见的有多个进程)。

从上面的例子中需要注意的是;假设我们做了如下的事情:

class MyApp extends Application {

  private String myState = /* complicated and slow initialization */;

  public String getState(){
    return myState;
  }
}

Now this slow initialization (such as hitting disk, hitting network, anything blocking, etc) will be performed every time Application is instantiated! You may think, well, this is only once for the process and I'll have to pay the cost anyways, right? For instance, as Dianne Hackborn mentions below, it is entirely possible for your process to be instantiated -just- to handle a background broadcast event. If your broadcast processing has no need for this state you have potentially just done a whole series of complicated and slow operations for nothing. Lazy instantiation is the name of the game here. The following is a slightly more complicated way of using Application which makes more sense for anything but the simplest of uses:

class MyApp extends Application {

  private MyStateManager myStateManager = new MyStateManager();

  public MyStateManager getStateManager(){
    return myStateManager ;
  }
}

class MyStateManager {

  MyStateManager() {
    /* this should be fast */
  }

  String getState() {
    /* if necessary, perform blocking calls here */
    /* make sure to deal with any multithreading/synchronicity issues */

    ...

    return state;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    ...
    MyStateManager stateManager = ((MyApp)getApplicationContext()).getStateManager();
    String state = stateManager.getState();
    ...
  }
}

虽然在这里我更喜欢应用程序子类化而不是使用单例对象作为更优雅的解决方案,但我宁愿开发人员在必要时使用单例对象,而不是完全不考虑将状态与应用程序子类关联的性能和多线程含义。

注1:同样正如anticafe所评论的,为了正确地将你的应用程序覆盖绑定到你的应用程序,在manifest文件中有一个标签是必要的。同样,更多信息请参见Android文档。一个例子:

<application
     android:name="my.application.MyApp" 
     android:icon="..."
     android:label="...">
</application>

注2:user608578在下面询问如何管理本机对象的生命周期。我不知道如何在Android上使用本机代码,我也没有资格回答如何与我的解决方案交互。如果有人确实有这个问题的答案,我愿意相信他们,并把这些信息放在这篇文章中以获得最大的能见度。

附录:

As some people have noted, this is not a solution for persistent state, something I perhaps should have emphasized more in the original answer. I.e. this is not meant to be a solution for saving user or other information that is meant to be persisted across application lifetimes. Thus, I consider most criticism below related to Applications being killed at any time, etc..., moot, as anything that ever needed to be persisted to disk should not be stored through an Application subclass. It is meant to be a solution for storing temporary, easily re-creatable application state (whether a user is logged in for example) and components which are single instance (application network manager for example) (NOT singleton!) in nature.

Dayerman has been kind enough to point out an interesting conversation with Reto Meier and Dianne Hackborn in which use of Application subclasses is discouraged in favor of Singleton patterns. Somatik also pointed out something of this nature earlier, although I didn't see it at the time. Because of Reto and Dianne's roles in maintaining the Android platform, I cannot in good faith recommend ignoring their advice. What they say, goes. I do wish to disagree with the opinions, expressed with regards to preferring Singleton over Application subclasses. In my disagreement I will be making use of concepts best explained in this StackExchange explanation of the Singleton design pattern, so that I do not have to define terms in this answer. I highly encourage skimming the link before continuing. Point by point:

Dianne states, "There is no reason to subclass from Application. It is no different than making a singleton..." This first claim is incorrect. There are two main reasons for this. 1) The Application class provides a better lifetime guarantee for an application developer; it is guaranteed to have the lifetime of the application. A singleton is not EXPLICITLY tied to the lifetime of the application (although it is effectively). This may be a non-issue for your average application developer, but I would argue this is exactly the type of contract the Android API should be offering, and it provides much more flexibility to the Android system as well, by minimizing the lifetime of associated data. 2) The Application class provides the application developer with a single instance holder for state, which is very different from a Singleton holder of state. For a list of the differences, see the Singleton explanation link above.

Dianne continues, "...just likely to be something you regret in the future as you find your Application object becoming this big tangled mess of what should be independent application logic." This is certainly not incorrect, but this is not a reason for choosing Singleton over Application subclass. None of Diane's arguments provide a reason that using a Singleton is better than an Application subclass, all she attempts to establish is that using a Singleton is no worse than an Application subclass, which I believe is false.

她接着说,“这就更自然地引出了你应该如何管理这些东西——根据需要初始化它们。”这忽略了一个事实,即没有理由不能使用Application子类按需初始化。同样没有区别。

Dianne ends with "The framework itself has tons and tons of singletons for all the little shared data it maintains for the app, such as caches of loaded resources, pools of objects, etc. It works great." I am not arguing that using Singletons cannot work fine or are not a legitimate alternative. I am arguing that Singletons do not provide as strong a contract with the Android system as using an Application subclass, and further that using Singletons generally points to inflexible design, which is not easily modified, and leads to many problems down the road. IMHO, the strong contract the Android API offers to developer applications is one of the most appealing and pleasing aspects of programming with Android, and helped lead to early developer adoption which drove the Android platform to the success it has today. Suggesting using Singletons is implicitly moving away from a strong API contract, and in my opinion, weakens the Android framework.

Dianne has commented below as well, mentioning an additional downside to using Application subclasses, they may encourage or make it easier to write less performance code. This is very true, and I have edited this answer to emphasize the importance of considering perf here, and taking the correct approach if you're using Application subclassing. As Dianne states, it is important to remember that your Application class will be instantiated every time your process is loaded (could be multiple times at once if your application runs in multiple processes!) even if the process is only being loaded for a background broadcast event. It is therefore important to use the Application class more as a repository for pointers to shared components of your application rather than as a place to do any processing!

以下是我从之前的StackExchange链接中偷来的关于singleton的缺点:

不能使用抽象类或接口类; 无法子类化; 跨应用程序的高耦合(难以修改); 难以测试(不能在单元测试中伪造/模拟); 在可变状态的情况下难以并行(需要大量的锁定);

加上我自己的:

不明确且难以管理的终身合同不适合Android(或大多数其他)开发;

在活动结果之前在简历上被调用。所以移动你的登录检查到恢复和你的第二次登录可以被阻止,一旦第二个活动已经返回积极的结果。On简历每次都会被调用,所以不用担心第一次没有被调用。

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

您可以使用一个静态字段来存储这种状态。或者把它放到资源Bundle中,然后在onCreate(Bundle savedInstanceState)上从那里恢复。只要确保你完全理解Android应用程序管理的生命周期(例如,为什么login()会在键盘方向改变时被调用)。