具有全局上下文的Android Singleton

Der*_*ard 45 android application-singleton

根据Android文档,它声明:

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

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

Bud*_*ius 84

另一个问题的编辑:

最近(截至2016年和大部分时间)我一直在做什么,并且我建议任何开发人员这样做:

使用Dagger2,只需使用Dagger 2.无论你需要什么,Context你都可以:

@Inject Context context;
Run Code Online (Sandbox Code Playgroud)

就是这样.在它的同时,注入所有其他可能是单身的东西.

编辑/改进答案:

因为这个答案变得有点流行,我会用最近我一直在使用的示例代码(截至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;
   }
}
Run Code Online (Sandbox Code Playgroud)

然后在任何需要访问context我懒惰的单例上以线程安全的方式使用双重检查同步,如下所述/sf/answers/781614851/

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();
}
Run Code Online (Sandbox Code Playgroud)

原始答案:

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

 public class SingletonDemo {
    private static SingletonDemo instance = null;

    private SingletonDemo() {       }

    public static SingletonDemo getInstance() {
            if (instance == null) {
                 instance = new SingletonDemo ();
            }
            return instance;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

 private Context context;
 init(Context context){
    this.context = context.getApplicationContext();
 }
Run Code Online (Sandbox Code Playgroud)

并记得把它叫做初始化单身人士.

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

  • "记得打电话"设计总会导致有人忘记打电话给它:)你什么时候打电话给它?首先调用`getInstance()`?另一种方式?你看到这会变得如此混乱. (3认同)
  • 关键是,你可以做各种各样的事情,但是如果你不需要,它会好很多.如果你创建一个`Application`类只是为了初始化你的单身人士,为什么我们甚至讨论这个?只需在`Application`类上放置一个`static getInstance()`并完成它. (3认同)
  • 而不是调用getInstance.init(this).我们不能只加一个参数的getInstance我们称之为的getInstance(本),当我们初始化实例中,我们设置的应用程序上下文.那不是更好吗? (2认同)
  • 不能保证在某些静态初始化代码尝试获取您的 Context 对象之前已调用非静态 `onCreate()`。 (2认同)

Mic*_*Tin 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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