LayoutInflater大家很熟悉,简单点说就是布局文件XML解析器,setContentView函数也是调用了LayoutInflater

用法:
View view = LayoutInflater.from(this).inflate(R.layout.activity_main, null);
LayoutInflater lyInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
上面的用法本质上都是一样.

控制台打印 重复调用LayoutInflater.from(this)  同一个进程下面 实例是单例
com.android.internal.policy.impl.PhoneLayoutInflater@420dcf80
com.android.internal.policy.impl.PhoneLayoutInflater@420dcf80
com.android.internal.policy.impl.PhoneLayoutInflater@420dcf80

   首先 LayoutInflater 是一个抽象类,实例化对象是从Service取出的。但是并没有到底层Binder去实例化对象。最终实例对象是PhoneLayoutInflater类

    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;
}

  

    从Activity父类可以找到 getSystemService方法
public Object getSystemService(String name) {
if (LAYOUT_INFLATER_SERVICE.equals(name)) {
if (mInflater == null) {
mInflater = LayoutInflater.from(mBase).cloneInContext(this); //在这个地方实例化的,主要关联到mBase Context对象实例
}
return mInflater;
}
return mBase.getSystemService(name);
}
    重点是Context的实例化对象 有个子类 ContextImpl.java 里面注册了相关Service
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
}
    SYSTEM_SERVICE_MAP 是个hashMap  注册的服务都存在这个地方,对象被缓存。
private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP = new HashMap<String, ServiceFetcher>(); abstract static class StaticServiceFetcher extends ServiceFetcher {
private Object mCachedInstance; @Override
public final Object getService(ContextImpl unused) {
synchronized (StaticServiceFetcher.this) {
Object service = mCachedInstance;
if (service != null) {
return service;
}
return mCachedInstance = createStaticService();
}
}
public abstract Object createStaticService(); //这个用于创建static服务
} registerService(LAYOUT_INFLATER_SERVICE, new ServiceFetcher() { //创建独立的对象 用于LayoutInflater
public Object createService(ContextImpl ctx) {
return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());
}});
    /*package*/ static class ServiceFetcher {
int mContextCacheIndex = -1; /**
* Main entrypoint; only override if you don't need caching.
*/
public Object getService(ContextImpl ctx) {// ContextImpl实例。
ArrayList<Object> cache = ctx.mServiceCache;
Object service;
synchronized (cache) {
if (cache.size() == 0) {
// Initialize the cache vector on first access.
// At this point sNextPerContextServiceCacheIndex
// is the number of potential services that are
// cached per-Context.
for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {
cache.add(null);
}
} else {
service = cache.get(mContextCacheIndex);//获取缓存是否存在
if (service != null) {
return service;
}
}
service = createService(ctx); //用来缓存服务实例
cache.set(mContextCacheIndex, service);
return service;
}
} /**
* Override this to create a new per-Context instance of the
* service. getService() will handle locking and caching.
*/
public Object createService(ContextImpl ctx) {
throw new RuntimeException("Not implemented");
}
}
    com.android.internal.policy.PolicyManager
找到了LayoutInflater的实现类 这个类算是个代理类 本质上是
private static final String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy"; policy\src\com\android\internal\policy\impl 目录下 public LayoutInflater makeNewLayoutInflater(Context context) {
return new PhoneLayoutInflater(context); //实例化
} policy\src\com\android\internal\policy\impl\PhoneLayoutInflater 回到LayoutInflater 递归解析XML 使用的是XMl Pull Parser解析器 public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) { }
    rInflate开始递归 都是XML解析

    void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs,
boolean finishInflate) throws XmlPullParserException, IOException { final int depth = parser.getDepth();
int type; 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)) {
parseRequestFocus(parser, parent);
} else if (TAG_INCLUDE.equals(name)) {
if (parser.getDepth() == 0) {
throw new InflateException("<include /> cannot be the root element");
}
parseInclude(parser, parent, attrs);
} else if (TAG_MERGE.equals(name)) {
throw new InflateException("<merge /> must be the root element");
} else if (TAG_1995.equals(name)) {
final View view = new BlinkLayout(mContext, attrs);
final ViewGroup viewGroup = (ViewGroup) parent;
final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
rInflate(parser, view, attrs, true);
viewGroup.addView(view, params);
} else {
final View view = createViewFromTag(parent, name, attrs);
final ViewGroup viewGroup = (ViewGroup) parent;
final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
rInflate(parser, view, attrs, true);
viewGroup.addView(view, params);
}
} if (finishInflate) parent.onFinishInflate();//解析完了,这个方法我们自定义可以复写 可以会去掉 子View的信息
}
基本上布局都是ViewGroup的子类 里面都有child view, 我们常用的findViewById 就是遍历去找对应ID的View
public final View findViewById(int id) {
if (id < 0) {
return null;
}
return findViewTraversal(id);
}
直接看ViewGroup中的findViewTraversal @Override
protected View findViewTraversal(int id) {
if (id == mID) { //等于自己
return this;
} final View[] where = mChildren;
final int len = mChildrenCount; for (int i = 0; i < len; i++) {
View v = where[i]; if ((v.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) { //IS_ROOT_NAMESPACE 可能是查询到最后一层了(猜的) 然后再遍历 查询
v = v.findViewById(id); if (v != null) {
return v;
}
}
} return null;
}

如果布局层级太深 解析XML和查找View都是耗费CPU的,所以做项目过程中 有必要进行布局优化。

本文源码: 4.1

Android LayoutInflater和findViewById 源码详解的更多相关文章

  1. Spark Streaming揭秘 Day25 StreamingContext和JobScheduler启动源码详解

    Spark Streaming揭秘 Day25 StreamingContext和JobScheduler启动源码详解 今天主要理一下StreamingContext的启动过程,其中最为重要的就是Jo ...

  2. spring事务详解(三)源码详解

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  3. 条件随机场之CRF++源码详解-预测

    这篇文章主要讲解CRF++实现预测的过程,预测的算法以及代码实现相对来说比较简单,所以这篇文章理解起来也会比上一篇条件随机场训练的内容要容易. 预测 上一篇条件随机场训练的源码详解中,有一个地方并没有 ...

  4. [转]Linux内核源码详解--iostat

    Linux内核源码详解——命令篇之iostat 转自:http://www.cnblogs.com/york-hust/p/4846497.html 本文主要分析了Linux的iostat命令的源码, ...

  5. saltstack源码详解一

    目录 初识源码流程 入口 1.grains.items 2.pillar.items 2/3: 是否可以用python脚本实现 总结pillar源码分析: @(python之路)[saltstack源 ...

  6. Shiro 登录认证源码详解

    Shiro 登录认证源码详解 Apache Shiro 是一个强大且灵活的 Java 开源安全框架,拥有登录认证.授权管理.企业级会话管理和加密等功能,相比 Spring Security 来说要更加 ...

  7. udhcp源码详解(五) 之DHCP包--options字段

    中间有很长一段时间没有更新udhcp源码详解的博客,主要是源码里的函数太多,不知道要不要一个一个讲下去,要知道讲DHCP的实现理论的话一篇博文也就可以大致的讲完,但实现的源码却要关心很多的问题,比如说 ...

  8. Activiti架构分析及源码详解

    目录 Activiti架构分析及源码详解 引言 一.Activiti设计解析-架构&领域模型 1.1 架构 1.2 领域模型 二.Activiti设计解析-PVM执行树 2.1 核心理念 2. ...

  9. 源码详解系列(六) ------ 全面讲解druid的使用和源码

    简介 druid是用于创建和管理连接,利用"池"的方式复用连接减少资源开销,和其他数据源一样,也具有连接数控制.连接可靠性测试.连接泄露控制.缓存语句等功能,另外,druid还扩展 ...

随机推荐

  1. GNU 网络程序

    ______________________________________________________________________________ | 版权声明 | | 1.本文可以转载.修 ...

  2. [BZOJ 1816] [Cqoi2010] 扑克牌 【二分答案】

    题目链接:BZOJ - 1816 题目分析 答案具有可以二分的性质,所以可以二分答案. 验证一个答案 x 是否可行,就累加一下各种牌相对于 x 还缺少的量,如果总和超过了 x 或 m ,就不可行. 因 ...

  3. unix io 模型浅析

    POSIX中对同步IO和异步IO的规定: 同步IO操作:引起进程的阻塞直到IO操作完成,异步IO操作:IO操作不会引起进程阻塞 在UNIX下,有5中操作模型: 阻塞IO,非阻塞IO,IO复用,信号驱动 ...

  4. 【面试】惠普IT电面

    1.英文自我介绍 一定要事先准备,逻辑要清晰 2.英文项目介绍

  5. 通过 IDE 向 Storm 集群远程提交 topology

    转载: http://weyo.me/pages/techs/storm-topology-remote-submission/ http://www.javaworld.com/article/20 ...

  6. 【转】图说Android的8年演变史

    原文网址:http://tech.gmw.cn/2016-02/17/content_18916338_14.htm 图说Android的8年演变史 我有话说    0      2011年10月谷歌 ...

  7. iOS应用架构浅谈

    (整理至http://www.cocoachina.com/ios/20150414/11557.html) 缘由 从事iOS工作一年多了,主要从事QQ钱包SDK开发和财付通app维护,随着对业务的慢 ...

  8. 总结linux无线命令wpa

    关于wpa_supplicant: 用到wpa_cli命令 wpa_cli -iwlan0 add_network             // wlan0 是无线网络设备的名字,增加一个网络,会返回 ...

  9. oracle 表查询(1)

    oracle 表基本查询 介绍在我们讲解的过程中我们利用scott 用户存在的几张表(emp,dept)为大家演示如何使用select语句,select 语句在软件编程中非常有用,希望大家好好的掌握. ...

  10. Contains Duplicate II ——LeetCode

    Given an array of integers and an integer k, find out whether there there are two distinct indices i ...