具有全局上下文的Android单例

具有全局上下文的Android单例,android,application-singleton,Android,Application Singleton,根据Android文档,它指出: 通常不需要对应用程序进行子类化。在大多数情况下, 静态单例可以以更模块化的方式提供相同的功能 对。如果您的单身汉需要全局上下文(例如注册 广播接收器),检索它的函数可以给定 内部使用Context.getApplicationContext()的上下文 首先构造单例 我如何创建一个具有全局上下文的静态单例,以便它在我的应用程序中的运行活动发生变化时能够生存?有一个引用getApplicationContext()的静态上下文就足够了吗?问题的另一个编辑(2016

根据Android文档,它指出:

通常不需要对应用程序进行子类化。在大多数情况下, 静态单例可以以更模块化的方式提供相同的功能 对。如果您的单身汉需要全局上下文(例如注册 广播接收器),检索它的函数可以给定 内部使用
Context.getApplicationContext()的上下文
首先构造单例

我如何创建一个具有全局上下文的静态单例,以便它在我的应用程序中的运行活动发生变化时能够生存?有一个引用getApplicationContext()的静态上下文就足够了吗?

问题的另一个编辑(2016)

最近(截至2016年及以后),我一直在做的事情,并将是我对任何开发人员的建议,是:

只用匕首2。无论您在哪里需要
上下文
,您都可以:

@Inject Context context;
就这样。在它的时候,注入所有其他的东西,这将是一个单身

编辑/改进答案(2014)

因为这个答案越来越流行,我将用我最近使用的示例代码(截至2014年7月)改进我自己的答案

首先让应用程序保留对自身的引用

public class App extends Application {
   private static App instance;
   public static App get() { return instance; }

   @Override
   public void onCreate() {
      super.onCreate();
      instance = this;
   }
}
然后,在需要访问
上下文的任何单例上,我使用双重检查同步以线程安全的方式延迟加载这些单例,如下所述

原始答案

文档建议使用

并在其中包含如下方法:

 private Context context;
 init(Context context){
    this.context = context.getApplicationContext();
 }
记住调用这个来初始化singleton


应用程序方法和单例方法之间的区别以及单例更好的原因在于文档
以更模块化的方式实现了相同的功能

我的应用程序中有这样的类:

public class ApplicationContext {

    private Context appContext;

    private ApplicationContext(){}

    public void init(Context context){
        if(appContext == null){
            appContext = context;
        }
    }

    private Context getContext(){
        return appContext;
    }

    public static Context get(){
        return getInstance().getContext();
    }

    private static ApplicationContext instance;

    public static ApplicationContext getInstance(){
        return instance == null ?
                (instance = new ApplicationContext()):
                    instance;
    }
}
然后,例如在启动活动中初始化它:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //init
    ApplicationContext.getInstance().init(getApplicationContext());
    //use via ApplicationContext.get()
    assert(getApplicationContext() == ApplicationContext.get());
}

一个单例有一个静态实例,一旦初始化,它将在您的进程的生命周期内“生存”。你到底有什么问题?明白了。在第一次阅读了上面段落的第二部分之后,我认为这意味着我需要对getApplicationContext()做一些事情,以便静态单例能够在Android应用程序的生命周期中生存。再读一遍后,我认为这只是意味着如果你需要使用上下文保存引用。例如:
publicstaticmyobjectgetinstance(Context c){}
Yes,类似这样的东西。您可以使参数
应用程序
更加类型安全,并保证不会传递活动等上下文。此外,您实际上不需要保存上下文,只需初始化您必须使用的内容。使用标准静态单例的生命周期是否与扩展应用程序对象相同?如果应用程序对象被扩展,应用程序的进程会持续更长时间吗?这取决于您对“生命周期”的理解。两者都在您的过程中持续存在<代码>应用程序
有一个
onCreate()
,保证在活动开始之前调用它。对于单例,初始化发生在您第一次调用
getInstance()
时。“记住调用”设计总是导致有人忘记调用它:)您何时调用它?先调用
getInstance()
?反过来说?你看,这会变得一团糟。关键是,你可以做各种各样的事情,但如果你不必做的话,那会好得多。如果您创建一个
应用程序
类只是为了初始化您的单例,那么我们为什么还要讨论这个问题呢?只需在您的
应用程序
类上放置一个
静态getInstance()
,并完成它,而不是调用getInstance.init(此)。我们不能只向getInstance添加一个参数,然后调用getInstance(this),当我们初始化实例时,我们设置应用程序上下文。这不是更好吗?不能保证在一些静态初始化代码尝试获取上下文对象之前调用了非静态的
onCreate()
。@Link88所有这些都只是使用单例应用程序的方法,两种方法都可以正常工作。这只是一个如何构造代码的问题。如今,对于任何比“Hello World”更重要的东西,我只需使用Dagger2注入我需要的任何东西,包括应用程序、上下文、存储、Http客户端等,等等。如果我将上下文放入weakreference中会更好吗?
public class ApplicationContext {

    private Context appContext;

    private ApplicationContext(){}

    public void init(Context context){
        if(appContext == null){
            appContext = context;
        }
    }

    private Context getContext(){
        return appContext;
    }

    public static Context get(){
        return getInstance().getContext();
    }

    private static ApplicationContext instance;

    public static ApplicationContext getInstance(){
        return instance == null ?
                (instance = new ApplicationContext()):
                    instance;
    }
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //init
    ApplicationContext.getInstance().init(getApplicationContext());
    //use via ApplicationContext.get()
    assert(getApplicationContext() == ApplicationContext.get());
}