52

根据 Android 文档,它指出:

通常不需要子类化 Application。在大多数情况下,静态单例可以以更模块化的方式提供相同的功能。如果您的单例需要全局上下文(例如注册广播接收器),则可以为检索它的函数提供一个上下文,该上下文Context.getApplicationContext()在首次构建单例时在内部使用。

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

4

2 回答 2

90

对问题的另一个编辑(2016)

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

只需使用 Dagger 2。无论您需要什么,Context您都可以:

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

然后在需要访问的任何单身人士上,context我使用双重检查同步以线程安全的方式延迟加载单身人士,如此处所述https://stackoverflow.com/a/11165926/906362

private static SingletonDemo instance;

public static SingletonDemo get() {
   if(instance == null) instance = getSync();
   return instance;
}

private static synchronized SingletonDemo getSync() {
   if(instance == null) instance = new SingletonDemo();
   return instance;
}

private SingletonDemo(){
   // here you can directly access the Application context calling
   App.get();
}

原始答案

文档的建议是使用普通的单例模式

 public class SingletonDemo {
    private static SingletonDemo instance = null;

    private SingletonDemo() {       }

    public static SingletonDemo getInstance() {
            if (instance == null) {
                 instance = new SingletonDemo ();
            }
            return instance;
    }
}

并在其中包含这样的方法:

 private Context context;
 init(Context context){
    this.context = context.getApplicationContext();
 }

并记得调用它来初始化单例。

Application 方法和 Singleton 方法之间的区别以及 Singleton 更好的原因在文档中same functionality in a more modular way

于 2012-12-27T16:23:26.380 回答
5

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

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

然后例如在 Launch Activity 中初始化它:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //init
    ApplicationContext.getInstance().init(getApplicationContext());
    //use via ApplicationContext.get()
    assert(getApplicationContext() == ApplicationContext.get());
}
于 2013-11-22T00:36:49.433 回答