LinearLayout具体解释三:LayoutInflater创建View过程分析
上次讲到以下这么一段代码,这段代码的作用就是解析xml文件成为view并显示到屏幕上的。
@Override
//设置contentview,也就是activity或fragment载入视图,即view的函数。接受的參数是资源id
public void setContentView(int layoutResID) {
//mContentParent是个ViewGroup ,这里mContentParent == null肯定是成立的
if (mContentParent == null) {
//成立后就会执行这一句话,从字面意思就能够看出,是安装解析器来着
installDecor();
} else {
mContentParent.removeAllViews();
}
//这一句话開始解析并初始化资源了
mLayoutInflater.inflate(layoutResID, mContentParent);
//取得对应的回调
final Callback cb = getCallback();
if (cb != null) {
//一旦有回调被调用了,就要通知视图改变
cb.onContentChanged();
}
}
纵观上面的一段代码,可能最实用的无非这么一句
mLayoutInflater.inflate(layoutResID, mContentParent);
他解析了id为layoutResId的资源。
mLayoutInflater这个成员变量,说起这个东西。又是一堆废话要讲。大家千万不要嫌我啰嗦。由于终于我会回到一个很实用的主题。在阐述这个主题之前。这些“小知识”都是必备的,就比方说爱爱之前总要来点前戏对吧
。
假设你听说过Fragment,那么应该知道fragment中载入视图是通过类似
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View layout = inflater.inflate(R.layout.main_activity_menu, null);
initLayouView(layout);
return layout;
}
这种代码实现的。
这就是inflate的作用。他就是用来解析xml并显示到屏幕的,至于解析的代码我这边就不多做阐述了,毕竟已经超越了我们的主题太远。我们还是看inflate是怎样给解析的xml分配内存。并加入到view上的吧!
这里是 v=source">LayoutInflater.java
当中inflate函数的实如今这里:
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
synchronized (mConstructorArgs) {
final AttributeSet attrs = Xml.asAttributeSet(parser);
mConstructorArgs[0] = mContext;
View result = root;
try {
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG &&
type != XmlPullParser.END_DOCUMENT) {
// Empty
}
if (type != XmlPullParser.START_TAG) {
throw new InflateException(parser.getPositionDescription()
+ ": No start tag found!");
}
//这里取得XML标签名字,比方说LinearLayout
final String name = parser.getName();
if (TAG_MERGE.equals(name)) {
if (root == null || !attachToRoot) {
throw new InflateException("<merge /> can be used only with a valid "
+ "ViewGroup root and attachToRoot=true");
}
rInflate(parser, root, attrs);
} else {
// 在此处创建视图,參数是前面取得的name,也就是说取得了LinearLayout開始new这个对象了!
第二个參数就是这个视图的属性
View temp = createViewFromTag(name, attrs);
//下面的代码省略......
以上的代码中。注意这一行:
View temp = createViewFromTag(name, attrs);
这一行就是通过解析tag来创建view的,这种方法的实现例如以下:
//这里的整个过程是:先推断是不是view,假设是的话。再取得属性值
View createViewFromTag(String name, AttributeSet attrs) {
if (name.equals("view")) {
name = attrs.getAttributeValue(null, "class");
} try {//这里的mFactory是一个叫做Factory的interface,在Inflater类构造的时候新建了mFactory对象
View view = (mFactory == null) ? null : mFactory.onCreateView(name,
mContext, attrs); if (view == null) {
if (-1 == name.indexOf('.')) {
view = onCreateView(name, attrs);
} else {
view = createView(name, null, attrs);
}
} //下面代码省略...
再关注里面的
view = createView(name, null, attrs);
这句话,正式開始创建了!
public final View createView(String name, String prefix, AttributeSet attrs)
throws ClassNotFoundException, InflateException {
//这里取得了xml的标签,比方说LinearLayout,这个构造器类是通过java的反射获取对象以及參数
Constructor constructor = sConstructorMap.get(name);
Class clazz = null; try {
if (constructor == null) {
// 这个是我们熟悉的类载入器。是另外一种初始化对象的方法(第一种是直接new出来)
clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name); if (mFilter != null && clazz != null) {
boolean allowed = mFilter.onLoadClass(clazz);
if (!allowed) {
failNotAllowed(name, prefix, attrs);
}
}
constructor = clazz.getConstructor(mConstructorSignature);
sConstructorMap.put(name, constructor);
} else {
// If we have a filter, apply it to cached constructor
if (mFilter != null) {
// Have we seen this name before?
Boolean allowedState = mFilterMap.get(name);
if (allowedState == null) {
// New class -- remember whether it is allowed
clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name); boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
mFilterMap.put(name, allowed);
if (!allowed) {
failNotAllowed(name, prefix, attrs);
}
} else if (allowedState.equals(Boolean.FALSE)) {
failNotAllowed(name, prefix, attrs);
}
}
} Object[] args = mConstructorArgs;
args[1] = attrs;
//上面取得了view,在这里又取得了attrs,换句话说,既取得了对象(比方说LinearLayout),又取得了參数(比方说高度,宽度等等)
return (View) constructor.newInstance(args);//下面代码省略...
创建成功了!
LinearLayout具体解释三:LayoutInflater创建View过程分析的更多相关文章
- Js基础知识4-函数的三种创建、四种调用(及关于new function()的解释)
在js中,函数本身属于对象的一种,因此可以定义.赋值,作为对象的属性或者成为其他函数的参数.函数名只是函数这个对象类的引用. 函数定义 // 函数的三种创建方法(定义方式) function one( ...
- 2019年6月14日 Web框架之Django_07 进阶操作(MTV与MVC、多对多表三种创建方式、前后端传输数据编码格式contentType、ajax、自定义分页器)
摘要 MTV与MVC 多对多表三种创建方式 ajax ,前后端传输数据编码格式contentType 批量插入数据和自定义分页器 一.MVC与MTV MVC(Model View Controller ...
- Android使用默认样式创建View的几个姿势
以下内容是分析安卓源码所得: 1: 使用默认样式创建View的方式, 源码文件 Button.Java 注:此文参考http://www.linzenews.com/ 中的内容所写,如侵删! 2: ...
- 使用Java代码来创建view
使用Java代码来创建view 一.简介 需要了解的知识 二.方法 1)java代码创建view方法 * 1.先建view对象 View view= View.inflate(this, R.layo ...
- Django-多对多关系的三种创建方式-forms组件使用-cookie与session-08
目录 表模型类多对多关系的三种创建方式 django forms 组件 登录功能手写推理过程 整段代码可以放过来 forms 组件使用 forms 后端定义规则并校验结果 forms 前端渲染标签组件 ...
- geotrellis使用(三)geotrellis数据处理过程分析
之前简单介绍了geotrellis的工作过程以及一个简单的demo,最近在此demo的基础上实现了SRTM DEM数据的实时分析以及高程实时处理,下面我就以我实现的上述功能为例,简单介绍一下geotr ...
- Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件
Fixflow引擎解析(四)(模型) - 通过EMF扩展BPMN2.0元素 Fixflow引擎解析(三)(模型) - 创建EMF模型来读写XML文件 Fixflow引擎解析(二)(模型) - BPMN ...
- VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池
VMware vSphere 服务器虚拟化之二十二桌面虚拟化之创建View Composer链接克隆的虚拟桌面池 在上一节我们创建了完整克隆的自动专有桌面池,在创建过程比较缓慢,这次我们将学习创建Vi ...
- IOS程序创建view
在IOS程序中创建view有六种方式 首先创建一个GLViewController类,继承UIViewController. 然后进入GLAppDelegate.m,在- (BOOL)applicat ...
随机推荐
- vs2012打开低版本项目时 出现vs2012警告未能加载包“visual c++ package 解决办法
vs2012 打开 vs2010 项目时 提示的 错误信息. 解决办法 是下载一个 vs2012的 一个补丁包 http://www.microsoft.com/en-us/download/deta ...
- windows :Tomcat免安装版环境变量配置 + jdk配置
1. 下载后解压,我解压的目录为:D:\Tomcat\apache-tomcat-9.0.1-windows-x64 2. 安装jdk和jre, 并配置环境变量: 2.1 用户变量新建JAVA_H ...
- python之路 --- python文件模式
文件模式: 打开文件的模式有: r,只读模式(默认). w,只写模式.[不可读:不存在则创建:存在则删除内容:] a,追加模式.[可读: 不存在则创建:存在则只追加内容:] "+&quo ...
- [git 学习篇]删除文件
1 现在本地文件管理器删除了readme.txt(这个readme.txt已经在创库存在的) rm -rf readme.txt 2 此时git status查看 $ git status # On ...
- Linux系统维护管理命令及vim编辑器
系统维护管理命令date.clear $>>date //显示或修改系统时间与日期. //%H:小时 %M:分钟 %S:秒 %Y完整年份 %d:日 %m:月份 eg: date " ...
- php中 ob_start()有什么作用
<?php ob_start(); //开启缓冲区 echo "这是第一次输出内容!\n"; $ff[1] = ob_get_contents() ; //获取当前缓冲区内容 ...
- ServletContext ActionContext ServletActionContext
1> ServletContext--------->SessionContext>RequestContext>PageContext 一个 WEB 运用程序只有一个 Ser ...
- 聊聊 Spring Boot 2.0 的 WebFlux
聊聊 Spring Boot 2.0 的 WebFlux## 前言 对照下 Spring Web MVC ,Spring Web MVC 是基于 Servlet API 和 Servlet 容器设计的 ...
- http client transfer
背景 在平时工作中我偶尔会写一些脚本监控HTTP接口的健康状况,基本上都是发送HTTP GET或HTTP POST请求,然后检测响应内容.但一直用的是WebClient和HttpWebRequest, ...
- 转 C++中不能声明为虚函数的有哪些函数
传送门 C++中不能声明为虚函数的有哪些函数 常见的不不能声明为虚函数的有:普通函数(非成员函数):静态成员函数:内联成员函数:构造函数:友元函数. 1.为什么C++不支持普通函数为虚函数? 普通函数 ...