经常使用 Context.getSystemService(String name)
获取一些系统服务。 其实这些服务都是以单例的方式注册在系统中的。 获取到的都是单例对象。
LayoutInflater 为例 在 View 中经常通过 LayoutInflater.from(Context context)
获取 LayoutInflater 对象,查看方法实现:
1 2 3 4 5 6 7 8 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(String key) 方法,查看 Context 类发现是个抽象方法,需要子类实现:
1 public abstract @Nullable Object getSystemService (@ServiceName @NonNull String name) ;
View 中的 Context 通常就是 Activity,Android 中在 Application,Activity,Service 中都存在 Context。一个应用中: Context 总数 = Activity 数 + Service 数 + 1 ( Application )。
所以从 Activity 的 Context 中分析 getSystemService 实现,先分析 Activity 的 Context 是在哪创建的。
Activity 的入口是 ActivityThread 的 main 函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static void main (String[] args) { ... Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false ); if (sMainThreadHandler == null ) { sMainThreadHandler = thread.getHandler(); } if (false ) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread" )); } ... Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited" ); }
创建 MainLooper,创建 ActivityThread 对象 ,启动 Looper 消息循环。ActivityThread 的 attach 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 private void attach (boolean system) { sCurrentActivityThread = this ; mSystemThread = system; if (!system) { RuntimeInit.setApplicationObject(mAppThread.asBinder()); final IActivityManager mgr = ActivityManager.getService(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } ...... }
不是系统应用(boolean system)会通过 Binder 机制与 ActivityManagerService 通信,最终调用 handleLaunchActivity
,里面又会调用 performLaunchActivity
方法:
1 2 3 4 5 6 7 8 9 10 11 12 private Activity performLaunchActivity (ActivityClientRecord r, Intent customIntent) { ... ActivityInfo aInfo = r.activityInfo; ... ContextImpl appContext = createBaseContextForActivity(r); ... activity.attach(appContext, this , getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback); ... }
ActivityThread createBaseContextForActivity 方法:
1 2 3 4 5 6 7 8 9 10 private ContextImpl createBaseContextForActivity (ActivityClientRecord r) { final int displayId; try { displayId = ActivityManager.getService().getActivityDisplayId(r.token); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } ContextImpl appContext = ContextImpl.createActivityContext(this , r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig); ... }
performLaunchActivity
里创建了 ContextImpl 对象,Context 的具体实现就是 ComtextImpl 了。查看 ContextImpl
里 getSystemService 实现:
1 2 3 public Object getSystemService (String name) { return SystemServiceRegistry.getSystemService(this , name); }
ContextImpl 里通过 SystemServiceRegistry
的类方法获取服务,查看 SystemServiceRegistry
类:
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 final class SystemServiceRegistry { private static final String TAG = "SystemServiceRegistry" ; private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES = new HashMap<Class<?>, String>(); private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new HashMap<String, ServiceFetcher<?>>(); private static int sServiceCacheSize; private SystemServiceRegistry () { } static { registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class , new CachedServiceFetcher <AccessibilityManager >() { @Override public AccessibilityManager createService (ContextImpl ctx) { return AccessibilityManager.getInstance(ctx); }}); registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class , new CachedServiceFetcher <LayoutInflater >() { @Override public LayoutInflater createService (ContextImpl ctx) { return new PhoneLayoutInflater(ctx.getOuterContext()); }}); ... } public static Object getSystemService (ContextImpl ctx, String name) { ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name); return fetcher != null ? fetcher.getService(ctx) : null ; } }
静态代码块里注册了很多服务, LayoutInflater 也是在这里注册的, 看到 LayoutInflater 的实现类是 PhoneLayoutInflater
。
PhoneLayoutInflater 获得了 LayoutInflater 之后,就该调用 inflate
加载,查看源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public View inflate (@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) { final Resources res = getContext().getResources(); if (DEBUG) { Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" (" + Integer.toHexString(resource) + ")" ); } final XmlResourceParser parser = res.getLayout(resource); try { return inflate(parser, root, attachToRoot); } finally { parser.close(); } }
继续查看:
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 public View inflate (XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) { synchronized (mConstructorArgs) { final Context inflaterContext = mContext; final AttributeSet attrs = Xml.asAttributeSet(parser); Context lastContext = (Context) mConstructorArgs[0 ]; mConstructorArgs[0 ] = inflaterContext; View result = root; try { int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { } final String name = parser.getName(); if (TAG_MERGE.equals(name)) { rInflate(parser, root, inflaterContext, attrs, false ); } else { final View temp = createViewFromTag(root, name, inflaterContext, attrs); ViewGroup.LayoutParams params = null ; ... if (root != null && attachToRoot) { root.addView(temp, params); } if (root == null || !attachToRoot) { result = temp; } ... rInflateChildren(parser, temp, attrs, true ); ... } } ... return result; } }
调用 createViewFromTag
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 View createViewFromTag (View parent, String name, Context context, AttributeSet attrs, boolean ignoreThemeAttr) { if (name.equals("view" )) { name = attrs.getAttributeValue(null , "class" ); } ... if (view == null ) { final Object lastContext = mConstructorArgs[0 ]; mConstructorArgs[0 ] = context; try { if (-1 == name.indexOf('.' )) { view = onCreateView(parent, name, attrs); } else { view = createView(name, null , attrs); } } finally { mConstructorArgs[0 ] = lastContext; } } return view; ... }
解析内置控件:调用 onCreateView
解析自定义控件:直接调用 createView(name, null, attrs);
前面分析了,Activity 的 Context 返回的 LayoutInflater 对象的具体实现是 PhoneLayoutInflater
,查看源码,发现其复写了 onCreateView
方法:
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 public class PhoneLayoutInflater extends LayoutInflater { private static final String[] sClassPrefixList = { "android.widget." , "android.webkit." , "android.app." }; ... @Override protected View onCreateView (String name, AttributeSet attrs) throws ClassNotFoundException { for (String prefix : sClassPrefixList) { try { View view = createView(name, prefix, attrs); if (view != null ) { return view; } } catch (ClassNotFoundException e) { } } return super .onCreateView(name, attrs); } }
所以,在 PhoneLayoutInflater 解析内置控件时,会使用3种前缀。
createView
在 LayoutInflater 中实现:
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 public final View createView (String name, String prefix, AttributeSet attrs) throws ClassNotFoundException, InflateException { Constructor<? extends View> constructor = sConstructorMap.get(name); if (constructor != null && !verifyClassLoader(constructor)) { constructor = null ; sConstructorMap.remove(name); } Class<? extends View> clazz = null ; try { if (constructor == null ) { clazz = mContext.getClassLoader().loadClass( prefix != null ? (prefix + name) : name).asSubclass(View.class ) ; if (mFilter != null && clazz != null ) { boolean allowed = mFilter.onLoadClass(clazz); if (!allowed) { failNotAllowed(name, prefix, attrs); } } constructor = clazz.getConstructor(mConstructorSignature); constructor.setAccessible(true ); sConstructorMap.put(name, constructor); } } ... final View view = constructor.newInstance(args); if (view instanceof ViewStub) { final ViewStub viewStub = (ViewStub) view; viewStub.setLayoutInflater(cloneInContext((Context) args[0 ])); } return view; }
这样就成功从 xml 构造了一个根 View,接着就会调用 rInflateChildren
创建子 View。 rInflateChildren 调用 rInflate
:
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 void rInflate (XmlPullParser parser, View parent, Context context, AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException { final int depth = parser.getDepth(); int type; boolean pendingRequestFocus = false ; while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { if (type != XmlPullParser.START_TAG) { continue ; } final String name = parser.getName(); if (TAG_REQUEST_FOCUS.equals(name)) { pendingRequestFocus = true ; consumeChildElements(parser); } else if (TAG_TAG.equals(name)) { parseViewTag(parser, parent, attrs); } else if (TAG_INCLUDE.equals(name)) { if (parser.getDepth() == 0 ) { throw new InflateException("<include /> cannot be the root element" ); } parseInclude(parser, context, parent, attrs); } else if (TAG_MERGE.equals(name)) { throw new InflateException("<merge /> must be the root element" ); } else { final View view = createViewFromTag(parent, name, context, attrs); final ViewGroup viewGroup = (ViewGroup) parent; final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs); rInflateChildren(parser, view, attrs, true ); viewGroup.addView(view, params); } } if (pendingRequestFocus) { parent.restoreDefaultFocus(); } if (finishInflate) { parent.onFinishInflate(); } }