[TOC]

概述

大家对LayoutInflater一定不陌生,它主要用于加载布局,在Fragment的onCreateView方法、ListView Adapter的getView方法等许多地方都可以见到它的身影。今天主要聊聊LayoutInflater的用法以及加载布局的工作原理。

在 Android UI 开发中,经常需要用到 LayoutInflater 类,它的基本作用是将 xml 布局文件解析成 View / View 树。除了基本的布局解析功能,LayoutInflater 还可以用于实现 动态换肤、视图转换、属性转换 等需求。

image-20221113233504242

LayoutInflater是什么?

LayoutInflater是一个用于将xml布局文件加载为View或者ViewGroup对象的工具,我们可以称之为布局加载器。

获取LayoutInflater

首先要注意LayoutInflater本身是一个抽象类,我们不可以直接通过new的方式去获得它的实例,通常有下面五种方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// 第一种: View.inflate(...)
public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
LayoutInflater factory = LayoutInflater.from(context);
return factory.inflate(resource, root);
}

// 第二种:
// 在Activity内部调用getLayoutInflater()方法
public LayoutInflater getLayoutInflater() {
//
return getWindow().getLayoutInflater();
}

// 第三种:
// PhoneWindow#getLayoutInflater()
private LayoutInflater mLayoutInflater;

public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}

public LayoutInflater getLayoutInflater() {
return mLayoutInflater;
}


// 第四种:
// LayoutInflater inflater = LayoutInflater.from(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;
}


// 第五种: context.getSystemService
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

从上面,我们可以看到,我们获取LayoutInflate归根结底最终都是调用getSystemService(…)的逻辑中。

所以,现在我们看getSystemService(…)内的逻辑:

1
2
3
4
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}

我们需要从SystemServiceRegistr中获取LAYOUT_INFLATER_SERVICE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// SystemServiceRegistry.java

private static final Map<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new ArrayMap<String, ServiceFetcher<?>>();

static {
...
1. 注册 Context.LAYOUT_INFLATER_SERVICE 与服务获取器
关注点:CachedServiceFetcher
关注点:PhoneLayoutInflater
registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class, new CachedServiceFetcher<LayoutInflater>() {
@Override
public LayoutInflater createService(ContextImpl ctx) {
注意:getOuterContext(),参数使用的是 ContextImpl 的代理对象,一般是 Activity
return new PhoneLayoutInflater(ctx.getOuterContext());
}});
...
}

2. 根据 name 获取服务对象
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}

注册服务与服务获取器
private static <T> void registerService(String serviceName, Class<T> serviceClass, ServiceFetcher<T> serviceFetcher) {
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}

3. 服务获取器创建对象
static abstract interface ServiceFetcher<T> {
T getService(ContextImpl ctx);
}
1
2
3
4
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
// root不为空时,attachToRoot默认为true
return inflate(resource, root, root != null);
}

rInflate方法

文章参考:https://www.jianshu.com/p/81a698aaf05c