Android Singleton с глобальным контекстом
В документации Android говорится:
Обычно нет необходимости создавать подкласс Application. В большинстве случаев статические синглтоны могут предоставлять ту же функциональность более модульным способом. Если вашему синглтону нужен глобальный контекст (например, для регистрации широковещательных приемников), функции для его извлечения может быть задан контекст, который внутренне использует
Context.getApplicationContext()
при первом создании синглтона.
Как я могу создать статический синглтон, имеющий глобальный контекст, чтобы он выдерживал изменение рабочей активности в моем приложении? Достаточно ли иметь статический контекст, который ссылается на getApplicationContext()?
2 ответа
еще одно изменение к вопросу:
в последнее время (на протяжении большей части 2016 года и далее), что я делал, и я бы предложил любому разработчику сделать это следующим образом:
Используйте Dagger2, просто используйте Dagger 2. Везде, где вам нужно Context
ты сделаешь:
@Inject Context context;
и это все. В то время как в это, вставьте все другие вещи, которые были бы одиночными.
отредактированный / улучшенный ответ:
поскольку этот ответ становится довольно популярным, я улучшу свой собственный ответ с примером кода того, что я использовал в последнее время (по состоянию на июль 2014 года).
Начните с того, что приложение хранит ссылку на себя.
public class App extends Application {
private static App instance;
public static App get() { return instance; }
@Override
public void onCreate() {
super.onCreate();
instance = this;
}
}
затем на любом синглтоне, который нуждается в доступе к context
Я лениво загружаю синглы потокобезопасным способом, используя двойную проверку синхронизации, как описано здесь /questions/5750799/java-singlton-i-sinhronizatsiya/5750812#5750812
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();
}
и не забудьте вызвать это, чтобы инициализировать синглтон.
Разница между прикладным подходом и подходом Singleton и тем, почему он лучше, находится в документации same functionality in a more modular way
У меня в приложении есть такой класс:
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());
}