Android单例。
推荐使用静态内部内实现单例或加了Volatile关键字的双重检查单例
使用容器实现单例模式
// 在程序的初始,将多种单例模式注入到一个统一的管理类中,在使用时根据key获取对应类型的对象。
public class SingletonManager {
// 使用HashMap作为缓存容器
private static Map<String, Object> objMap = new HashMap<String,Object>();
private Singleton() {}
public static void registerService(String key, Objectinstance) {
if (!objMap.containsKey(key) ) {
objMap.put(key, instance); //第一次是存入Map
}
}
public static Object getService(String key) {
return objMap.get(key); //返回与key相对应的对象
}
}
LayoutInflater的单例模式实现
在日常开发中,我们经常使用系统提供的服务,如WindowManagerService,PackageManagerService,ActivityManagerService等,
但是我们最经常使用的一定少不了LayoutInflater,这些服务会在合适的时候以单例的形式注册在系统中,
我们需要的时候只需要通过context.getSystemService(String serviceName)方法获取即可。
LayoutInflater mInflater = LayoutInflater.from(this);
1.通过LayoutInflater.from(context)来获取LayoutInflater服务
LayoutInflater mInflater = LayoutInflater.from(this);
public static LayoutInflater from(Context context) {
LayoutInflater LayoutInflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (LayoutInflater == null) {
throw new AssertionError("LayoutInflater not found.");
}
return LayoutInflater;
}
2.context.getSystemService是怎么工作的,context的实现类是ContextImpl类,点进去看一下
// ContextImpl用来缓存已经创建的服务实例
final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
3.SystemServiceRegistry类中
// 容器类
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
/**
* Gets a system service from a given context.
*/
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
/**
* Statically registers a system service with the context.
* This method must be called during static initialization only.
*/
private static <T> void registerService(String serviceName, Class<T> serviceClass,
ServiceFetcher<T> serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
5.服务都是在什么时候注册的?
static {
registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
new CachedServiceFetcher<LayoutInflater>() {
@Override
public LayoutInflater createService(ContextImpl ctx) {
return new PhoneLayoutInflater(ctx.getOuterContext());
}});
// 我们使用的ActivityManager在这注册
registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
new CachedServiceFetcher<ActivityManager>() {
@Override
public ActivityManager createService(ContextImpl ctx) {
return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
}});
// 我们使用的AlarmManager在这注册
registerService(Context.ALARM_SERVICE, AlarmManager.class,
new CachedServiceFetcher<AlarmManager>() {
@Override
public AlarmManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
IAlarmManager service = IAlarmManager.Stub.asInterface(b);
return new AlarmManager(service, ctx);
}});
}
- 很明显,这是在一个静态的代码块进行注册服务,第一次加载该类的时候执行,并且只执行一次,保证实例的唯一性
- 从这个过程中可以看出,系统将服务以键值对的形式存储在HashMap中,用户使用时只需要获取具体的服务对象,
第一次获取时,调用getSystemService来获取具体的对象,
在第一次调用时,会调用registerService通过map将对象缓存在一个列表中,
下次再用时直接从容器中取出来就可以。避免重复创建对象,从而达到单例的效果。减少了资源消耗。 - 在Android源码中,APP启动的时候,虚拟机第一次加载该类时会注册各种ServiceFetcher,比如LayoutInflater Service。
将这些服务以键值对的形式存储在一个HashMap中,用户使用时只需要根据key来获取到对应的ServiceFetcher,
然后通过ServiceFetcher对象的getService函数获取具体的服务对象。
当第一次获取时,会调用ServiceFetcher的createService函数创建服务对象,然后将该对象缓存到一个列表中,
下次再取时直接从缓存中获取,避免重复创建对象,从而达到单例的效果。Android中的系统核心服务以单例形式存在,减少了资源消耗。
分析下getService流程如下:
首先从ContextImpl缓存数组中获取对应的实例。
如果实例存在,直接返回实例对象;否则创建实例,并加入ContextImpl缓存数组中。
CachedServiceFetcher的实现了保证了,实例对象只在首次获取时才会被初始化,否则就返回已经缓存的对象,节省了系统资源。
综合分析我们得出如下结论:
- 我们常用的一些系统Service是通过SystemServiceRegistry进行管理的。
- 系统加载SystemServiceRegistry类时,通过静态块将各种服务类存储在
- SYSTEM_SERVICE_FETCHERS(HashMap<ServiceName, ServiceFetcher>)中,每一个具体的服务类都对应一个ServiceFetcher。
- 使用时从HashMap中获取ServiceFetcher,并从中获取需要的实例,获取的实例被缓存在ContextImpl中备用。
- CachedServiceFetcher负责创建具体的实例,并将实例缓存到ContextImpl的缓存数组中。
涉及单例模式的几个要点:
- SystemServiceRegistry使用HashMap管理ServiceFetcher。
- ServiceFetcher保证实例只创建一次,且通过使用synchronized机制保证多线程安全。
- 加入缓存机制,保证实例只会被创建一次。
EventBus(主要是使用双重检查DCL)
这样的话它的资源利用率会很高,并且第一次执行的时候,是单例对象才会被实例化,但是第一次加载的时候会稍慢,可以被接受.
static volatile EventBus defaultInstance;
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
ImageLoader图片加载框架
ImageLoader.getInstance();// 在自己的Application中创建全局实例
.....
//getInstance() 执行的源码
public static ImageLoader getInstance() {
if(instance == null) {//双重校验DCL单例模式
Class var0 = ImageLoader.class;
synchronized(ImageLoader.class) {//同步代码块
if(instance == null) {
instance = new ImageLoader();//创建一个新的实例
}
}
}
return instance;//返回一个实例
}
Glide源码分析--单例。
Glide.with(this).load("").into(new ImageView(this));
public static RequestManager with(@NonNull Context context) {
return getRetriever(context).get(context); // 传入上下文
}
private static RequestManagerRetriever getRetriever(@Nullable Context context) {
return Glide.get(context).getRequestManagerRetriever();
}
// Glide单例对象,然后我们来具体分析下它是怎么实现的。很明显它使用的二次判空的双重检查机制,保证的对象的单一性质,不会因为多个线程的访问而导致创建多个对象,破坏了单例设计模式的单一性质。
private static volatile Glide glide;
//第一次判断是为了验证是否创建对象,判断为了避免不必要的同步。
//第二次判断是为了避免重复创建单例,因为可能会存在多个线程通过了第一次判断在等待锁,来创建新的实例对象。
public static Glide get(@NonNull Context context) {
if (glide == null) {
GeneratedAppGlideModule annotationGeneratedModule =
getAnnotationGeneratedGlideModules(context.getApplicationContext());
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context, annotationGeneratedModule);
}
}
}
return glide;
}
@GuardedBy("Glide.class")
private static void checkAndInitializeGlide(
@NonNull Context context, @Nullable GeneratedAppGlideModule generatedAppGlideModule) {
if (isInitializing) {
throw new IllegalStateException(
"You cannot call Glide.get() in registerComponents(),"
+ " use the provided Glide instance instead");
}
isInitializing = true;
initializeGlide(context, generatedAppGlideModule);
isInitializing = false;
}
进到initializeGlide()函数里面去看,Glide glide = builder.build(applicationContext);
看到这句代码则是构建了一个Glide对象,最后经过一系列操作Glide.glide = glide;
将这个对象赋值给成员变量,自此Glide单例创建对象分析结束。
@GuardedBy("Glide.class")
@SuppressWarnings("deprecation")
private static void initializeGlide(
@NonNull Context context,
@NonNull GlideBuilder builder,
@Nullable GeneratedAppGlideModule annotationGeneratedModule) {
Context applicationContext = context.getApplicationContext();
List<com.bumptech.glide.module.GlideModule> manifestModules = Collections.emptyList();
if (annotationGeneratedModule == null || annotationGeneratedModule.isManifestParsingEnabled()) {
manifestModules = new ManifestParser(applicationContext).parse();
}
if (annotationGeneratedModule != null
&& !annotationGeneratedModule.getExcludedModuleClasses().isEmpty()) {
Set<Class<?>> excludedModuleClasses = annotationGeneratedModule.getExcludedModuleClasses();
Iterator<com.bumptech.glide.module.GlideModule> iterator = manifestModules.iterator();
while (iterator.hasNext()) {
com.bumptech.glide.module.GlideModule current = iterator.next();
if (!excludedModuleClasses.contains(current.getClass())) {
continue;
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "AppGlideModule excludes manifest GlideModule: " + current);
}
iterator.remove();
}
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
for (com.bumptech.glide.module.GlideModule glideModule : manifestModules) {
Log.d(TAG, "Discovered GlideModule from manifest: " + glideModule.getClass());
}
}
RequestManagerRetriever.RequestManagerFactory factory =
annotationGeneratedModule != null
? annotationGeneratedModule.getRequestManagerFactory()
: null;
builder.setRequestManagerFactory(factory);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
module.applyOptions(applicationContext, builder);
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.applyOptions(applicationContext, builder);
}
Glide glide = builder.build(applicationContext);
for (com.bumptech.glide.module.GlideModule module : manifestModules) {
try {
module.registerComponents(applicationContext, glide, glide.registry);
} catch (AbstractMethodError e) {
throw new IllegalStateException(
"Attempting to register a Glide v3 module. If you see this, you or one of your"
+ " dependencies may be including Glide v3 even though you're using Glide v4."
+ " You'll need to find and remove (or update) the offending dependency."
+ " The v3 module name is: "
+ module.getClass().getName(),
e);
}
}
if (annotationGeneratedModule != null) {
annotationGeneratedModule.registerComponents(applicationContext, glide, glide.registry);
}
applicationContext.registerComponentCallbacks(glide);
Glide.glide = glide; // 赋值。
}
网友评论