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. [BZOJ 3791] 作业 【DP】

    题目链接:BZOJ - 3791 题目分析 一个性质:将一个序列染色 k 次,每次染连续的一段,最多将序列染成 2k-1 段不同的颜色. 那么就可以 DP 了,f[i][j][0|1] 表示到第 i ...

  2. Blue Jeans

    Description The Genographic Project is a research partnership between IBM and The National Geographi ...

  3. Hibernate 配置详解(2)

    6) hibernate.session_factory_name: 配置一个JNDI名称,通过Configuration对象创建的SessionFactory会绑定到JNDI下该名称中.一般名字格式 ...

  4. 账户管理groupadd groupmod groupdel usermod usermod userdel

    http://www.cnblogs.com/ggjucheng/archive/2012/08/21/2648380.html http://blog.csdn.net/qq1603013767/a ...

  5. 【转】Java 枚举7常见种用法

    原文网址:http://softbeta.iteye.com/blog/1185573 Java 枚举7常见种用法 博客分类: java java枚举enmu  原创地址:http://blog.li ...

  6. 【模拟】Codeforces 705B Spider Man

    题目链接: http://codeforces.com/problemset/problem/705/B 题目大意: 两个人玩游戏,总共N个数,分别求前I(I=1 2 3...n)个数时游戏的获胜者是 ...

  7. 【动态规划】Vijos P1104 采药(NOIP2005普及组第三题)

    题目链接: https://vijos.org/p/1104 题目大意: T时间,n个物品,每个耗时ti,可获得收益ci,求最大收益. 题目思路: [动态规划] 01背包裸题.一维二维都过了,放个一维 ...

  8. 【转】Ansys 13.0 flexlm not running完美解决方案

    http://jingyan.baidu.com/article/af9f5a2dd9843a43150a4550.html 实测,12.1 用此方法问题同样得解.

  9. 《精通CSS:高级Web标准解决方案》学习笔记(上)

    鉴于国产CSS书籍基本都是辣鸡的现状,我在半年前动用某工作室的购书资金采购了一些技术书籍,这本广受好评的<精通CSS>也在其中.但是在阅读过后我深深的感觉到,如果说CSS本来已经是一种很琐 ...

  10. 动软代码生成器 可用于生成Entity层,可更改模板 /codesmith 也可以

    动软代码生成器官方下载地址:http://www.maticsoft.com/download.aspx 教程:http://jingyan.baidu.com/article/219f4bf7dfd ...