LayoutInflater 的实例化
LayoutInflater 的构造器是 protected ,外部无法直接实例化,只能通过两种方式得到其对象
- LayoutInflater.from(context)
- activity.getLayoutInflater
源码分析
Activity
/**
* Convenience for calling
* {@link android.view.Window#getLayoutInflater}.
*/
@NonNull
public LayoutInflater getLayoutInflater() {
return getWindow().getLayoutInflater();
}
实际就是 PhoneWindow 中的属性 mLayoutInflater
public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}
而 PhoneWindow 中的属性赋值也是通过 LayoutInflater.from(context) 得到的inflater 实例
那么直接追踪 LayoutInflater.from(context) 即可
LayoutInflter
/**
* Obtains the LayoutInflater from the given context.
*/
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;
}
通过 getSystemService 获取实例
context 的具体实现都在 ContextImpl 中
ContextImpl
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
SystemServiceRegistry
/**
* 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;
}
这里才是真正 实例获取 的地方,那么这个 SYSTEM_SERVICE_FETCHERS 是怎么被放置了 inflater 的实例呢?
SystemServiceRegistry
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
static {
...
registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
new CachedServiceFetcher<LayoutInflater>() {
@Override
public LayoutInflater createService(ContextImpl ctx) {
return new PhoneLayoutInflater(ctx.getOuterContext());
}});
...
}
这里我们看到当 类 SystemServiceRegistry 被引用的时候,SYSTEM_SERVICE_FETCHERS 就被静态语句块初始化并装填内容了,那么这个 ServiceFetcher 是个什么东西呢?
SystemServiceRegistry
/**
* Base interface for classes that fetch services.
* These objects must only be created during static initialization.
*/
static abstract interface ServiceFetcher<T> {
T getService(ContextImpl ctx);
}
/**
* Override this class when the system service constructor needs a
* ContextImpl and should be cached and retained by that context.
*/
static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
private final int mCacheIndex;
public CachedServiceFetcher() {
mCacheIndex = sServiceCacheSize++;
}
@Override
@SuppressWarnings("unchecked")
public final T getService(ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
synchronized (cache) {
// Fetch or create the service.
Object service = cache[mCacheIndex];
if (service == null) {
try {
service = createService(ctx);
cache[mCacheIndex] = service;
} catch (ServiceNotFoundException e) {
onServiceNotFound(e);
}
}
return (T)service;
}
}
public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
}
到了这里基本上就很清晰了,在 静态语句块中 将一个 实例生成器 存进 SYSTEM_SERVICE_FETCHERS 中了,然后每次调用通过接口开放的方法 getService 来获取指定的实例。
==备注==:SYSTEM_SERVICE_FETCHERS 仅是存储了,每个 Service 实例的生成器,但是具体的 Service 实例并未被生成
仔细分析 CachedServiceFetcher 这个类的源码,其类名中包含一个 Cache,理所当然的可以想到,不可能每次调用一下 LayoutInflater.from(context) 都要重新生成一个 inflater 的实例吧?这里的 Cache 做了解释。
ContextImpl
// The system service cache for the system services that are cached per-ContextImpl.
final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
SystemServiceRegistry
/**
* Creates an array which is used to cache per-Context service instances.
*/
public static Object[] createServiceCache() {
return new Object[sServiceCacheSize];
}
就是基于当前 ContextImpl 实例下,有一个 mServiceCache 缓存数组,用来缓存当前 Context 下曾经被初始化过的 Service 实例。当这个 mServiceCache 数组找不到对应的实例(即:当前Context 下还未被初始化过 对应的 Service实例),就会执行 CachedServiceFetcher 中的getService 逻辑,具体的执行 实例的初始化逻辑,并将生成的实例缓存进去。
所以 LayoutInflater.from(context) 得到的inflatr 实例,当 Context 相同时,得到的 inflater 都是同一个实例。
关于 Context 与 ContextImpl 可以阅读2018-09-19-Context区分