“三更灯火五更鸡,正是男儿读书时。” –颜真卿
正文
说到LayoutInflater可能大家首先想到的是加载layout,一般我们会习惯性的调用View中的这个静态方法
1
2
3
4
public static View inflate(Context context, int resource, ViewGroup root) {
LayoutInflater factory = LayoutInflater.from(context);
return factory.inflate(resource, root);
}
或者直接得到LayoutInflater对象,然后调用它的下面方法
inflate
1
2
3
4
5
6
7
8
9
public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
if (DEBUG) System.out.println("INFLATING from resource: " + resource);
XmlResourceParser parser = getContext().getResources().getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
}
可是LayoutInflater是个抽象方法,我们是不能直接初始化的,一般都是这样来得到这个对象的
1
2
LayoutInflater LayoutInflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
我们通过查看源码,发现上面的方法在Context中也是也抽象方法,并没有真正的实现
getSystemService
1
public abstract Object getSystemService(String name);
今天我们就来一步步分析怎么得到LayoutInflater这个对象的,至于他的inflate方法我们也是经常遇到的,这篇我们先跳过,下一篇在作详解,上面说到我们在Context中发现他是一个抽象类,那么我们就去它的子类中查找,在ContextWrapper中我们终于找到了,
1
2
3
4
@Override
public Object getSystemService(String name) {
return mBase.getSystemService(name);
}
那么我们在看看mBase是什么,可能很失望,它就是传进来的Context
attachBaseContext
1
2
3
4
5
6
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
我们继续跟踪,找到ContextWrapper的一个子类ContextThemeWrapper,发现getSystemService方法正好有我们要找的LayoutInflater,可是却没什么用,因为它需要实例化之后才能克隆,
1
2
3
4
5
6
7
8
9
@Override public Object getSystemService(String name) {
if (LAYOUT_INFLATER_SERVICE.equals(name)) {
if (mInflater == null) {
mInflater = LayoutInflater.from(mBase).cloneInContext(this);
}
return mInflater;
}
return mBase.getSystemService(name);
}
我们继续找它的下一个子类Activity,找到了,可是并没有我们要找的LayoutInflater
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public Object getSystemService(String name) {
if (getBaseContext() == null) {
throw new IllegalStateException(
"System services not available to Activities before onCreate()");
}
if (WINDOW_SERVICE.equals(name)) {
return mWindowManager;
} else if (SEARCH_SERVICE.equals(name)) {
ensureSearchManager();
return mSearchManager;
}
return super.getSystemService(name);
}
饶了一大圈白费力气结果还是没找到。不要气馁,回到刚才我们说的ContextWrapper类中的getSystemService方法,我们来看一下mBase是怎么传进来的,最终我们在Activity的这个方法找到了它
attach
1
2
3
4
5
6
7
8
9
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config) {
attachBaseContext(context);
…………………………
}
在之前我们讲过Activity的attach方法是在ActivityThreaad的performLaunchActivity方法中传进来的,
performLaunchActivity
1
2
3
4
5
6
7
8
9
10
11
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
…………………………
Context appContext = createBaseContextForActivity(r, activity);
…………………………
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
…………………………
return activity;
}
也就是说ContextWrapper中的mBase其实就是在这里传进来的,我们继续查看createBaseContextForActivity方法
createBaseContextForActivity
1
2
3
4
5
6
private Context createBaseContextForActivity(ActivityClientRecord r,
final Activity activity) {
ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
……………………
return baseContext;
}
看到了吧,其实Context的真正实现类是ContextImpl
1
2
3
4
5
/**
* Common implementation of Context API, which provides the base
* context object for Activity and other application components.
*/
class ContextImpl extends Context {
找到它就好办了,我们来查找一下getSystemService方法
1
2
3
4
5
@Override
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
}
看到没,其实SYSTEM_SERVICE_MAP就是个HashMap,那它究竟是怎么保存进去的,我们继续查看,发现有一个方法叫registerService,在这里面保存的
registerService
1
2
3
4
5
6
private static void registerService(String serviceName, ServiceFetcher fetcher) {
if (!(fetcher instanceof StaticServiceFetcher)) {
fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
}
SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
}
我们还发现了有一个静态代码块,存进去的比较多,我们随便找几个我们平时比较常见的看看
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
static {
…………………………
registerService(ACTIVITY_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
}});
registerService(ALARM_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(ALARM_SERVICE);
IAlarmManager service = IAlarmManager.Stub.asInterface(b);
return new AlarmManager(service, ctx);
}});
registerService(AUDIO_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new AudioManager(ctx);
}});
…………………………
registerService(INPUT_SERVICE, new StaticServiceFetcher() {
public Object createStaticService() {
return InputManager.getInstance();
}});
registerService(DISPLAY_SERVICE, new ServiceFetcher() {
@Override
public Object createService(ContextImpl ctx) {
return new DisplayManager(ctx.getOuterContext());
}});
registerService(INPUT_METHOD_SERVICE, new StaticServiceFetcher() {
public Object createStaticService() {
return InputMethodManager.getInstance();
}});
………………………………
………………………………
registerService(LAYOUT_INFLATER_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());
}});
………………………………
………………………………
// Note: this was previously cached in a static variable, but
// constructed using mMainThread.getHandler(), so converting
// it to be a regular Context-cached service...
registerService(POWER_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(POWER_SERVICE);
IPowerManager service = IPowerManager.Stub.asInterface(b);
return new PowerManager(ctx.getOuterContext(),
service, ctx.mMainThread.getHandler());
}});
registerService(SEARCH_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new SearchManager(ctx.getOuterContext(),
ctx.mMainThread.getHandler());
}});
…………………………
registerService(TELEPHONY_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new TelephonyManager(ctx.getOuterContext());
}});
…………………………
registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new SystemVibrator(ctx);
}});
registerService(WALLPAPER_SERVICE, WALLPAPER_FETCHER);
registerService(WIFI_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(WIFI_SERVICE);
IWifiManager service = IWifiManager.Stub.asInterface(b);
return new WifiManager(ctx.getOuterContext(), service);
}});
registerService(WIFI_P2P_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(WIFI_P2P_SERVICE);
IWifiP2pManager service = IWifiP2pManager.Stub.asInterface(b);
return new WifiP2pManager(service);
}});
…………………………
registerService(CAMERA_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new CameraManager(ctx);
}
});
…………………………
}
然后我们在找我们需要的LayoutInflater,就是两条杠之间的,我们找到PolicyManager类,然后找到相应的方法
makeNewLayoutInflater
1
2
3
public static LayoutInflater makeNewLayoutInflater(Context context) {
return sPolicy.makeNewLayoutInflater(context);
}
sPolicy其实就是Policy,我们来查看一下它的源码,找到相应的方法
1
2
3
public LayoutInflater makeNewLayoutInflater(Context context) {
return new PhoneLayoutInflater(context);
}
看这里我们终于明白了,其实我们通过getSystemService得到的LayoutInflater 就是PhoneLayoutInflater,其实他继承的是LayoutInflater,我们可以看一下
1
public class PhoneLayoutInflater extends LayoutInflater {
好了,到此为止LayoutInflater LayoutInflater =(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);这个方法我们已经分析完了,其实他得到的就是PhoneLayoutInflater这个类,有时间我们在来分析一下它的inflate方法,也是我们最常用到的一个方法。