在日常开发中经常会用到通过资源id去获取view的场景,LayoutInflater这时非常有用。这与我们经常用的findViewById()不一样。

LayoutInflater通常用于动态载入的界面,使用LayoutInflater的inflate方法动态接入layout文件;

findViewById通常用于在已经载入的界面,使用findViewById()方法来获得其中的界面元素。

一 LayoutInflater实例

获得LayoutInflater实例方式

通过系统服务获取布局加载器

LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

通过activity中的getLayoutInflater()方法

LayoutInflater inflater = getLayoutInflater();

通过LayoutInflater的from静态方法

LayoutInflater inflater = LayoutInflater.from(this)

这三种方式本质都是调用Context.getSystemService()。

getLayoutInflater()源码分析

Activity 的 getLayoutInflater() 方法是调用 PhoneWindow 的getLayoutInflater()方法,看一下该源代码:

public PhoneWindow(Context context) {

super(context);

//可以看出它其实是调用 LayoutInflater.from(context)。

mLayoutInflater = LayoutInflater.from(context);

}

LayoutInflater.from(context)源码分析

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;

}

LayoutInflater.from(context)内部是调用context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)获得布局加载器.

二 inflate方法

既然已经获取到LayoutInflater实例,加载布局主要还是LayoutInflater的inflate方法。

LayoutInflater类提供的下面四种inflate方法:

public View inflate (int resource, ViewGroup root)

public View inflate (int resource, ViewGroup root, boolean attachToRoot)

public View inflate (XmlPullParser parser, ViewGroup root)

public View inflate (XmlPullParser parser, ViewGroup root, boolean attachToRoot)

我们先看下源码:

public View inflate(int resource, ViewGroup root) {

//如果root不为null,attachToRoot为true,否则attachToRoot为false

return inflate(resource, root, root != null);

}

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();

}

}

下图可以看到inflate的调用关系:

具体处理加载逻辑的是inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)方法,具体XmlPullParser的解析,不是我们讨论的主题。我们这里主要讨论的是上面两个方法的参数变化影响。因为我们通常是调用上面连个方法来加载布局。

说的更明白一点就是对 ViewGroup root, boolean attachToRoot这两个参数的讨论。传入ViewGroup root, boolean attachToRoot的值不同,会出现什么结果呢?

先初略解释下这两个参数:

ViewGroup root:指实例的布局所要放入的根视图。

boolean attachToRoot:指是否附加到传入的根视图。

继续看下inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)源码,然后在分析每种情况。

// 这里加载我们设置的resource,临时标记为temp

final View temp = createViewFromTag(root, name, attrs, false);

ViewGroup.LayoutParams params = null;

if (root != null) {

if (DEBUG) {

System.out.println("Creating params from root: " +

root);

}

// 如果root不是null,会根据resource最外面的layout创建layout params来匹配root(如果需要)

params = root.generateLayoutParams(attrs);

if (!attachToRoot) {

// 如果attachToRoot为false,为temp设置布局

temp.setLayoutParams(params);

}

......

//如果root != null && attachToRoot,把temp添加到root中,并设置params

if (root != null && attachToRoot) {

root.addView(temp, params);

}

//如果root == null || !attachToRoot,直接返回temp。

if (root == null || !attachToRoot) {

result = temp;

}

......

return result;

这里稍微分析代码:

第1段代码:动态载入resource

final View temp = createViewFromTag(root, name, attrs, false)

第2段代码:创建ViewGroup的LayoutParams

ViewGroup.LayoutParams params = null;

params = root.generateLayoutParams(attrs);

第3段代码:当root不为空,attachToRoot为false时,为temp设置layout属性,当该view以后被添加到父view当中时,这些layout属性会自动生效

if (root != null) {

params = root.generateLayoutParams(attrs);

if (!attachToRoot) {

// 如果attachToRoot为false,为temp设置布局

temp.setLayoutParams(params);

}

第4段代码:

// We are supposed to attach all the views we found (int temp)

// to root. Do that now.

if (root != null && attachToRoot) {

root.addView(temp, params);

}

// Decide whether to return the root that was passed in or the

// top view found in xml.

if (root == null || !attachToRoot) {

result = temp;

}

只有当root != null && attachToRoot)时,root会把temp添加到root中,给加载的布局文件的指定一个父布局,即root。否则temp不会添加到root,即root == null || !attachToRoot时,最后直接return temp。

这里总结一下:

public View inflate(int resource, ViewGroup root, boolean attachToRoot)

如果root为null,attachToRoot为任何值都毫无意义,只会单纯的加载布局文件。

如果root不为null,attachToRoot设为true,root会把temp添加到root中,此时在temp布局文件中的根view的layout属性会生效。

如果root不为null,attachToRoot设为false,此时view并没有添加到root,但是view的layout属性被保存了下来,以后如果调用addView(View child),layout属性会自动生效。可以见下面源码:ViewGroup

public void addView(View child, int index) {

if (child == null) {

throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");

}

//这里便是从child中获取LayoutParams

LayoutParams params = child.getLayoutParams();

if (params == null) {

params = generateDefaultLayoutParams();

if (params == null) {

throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");

}

}

//这段代码是不是和刚才inflate中代码很相似,对,这里就是把view和layout属性添加到parent中。

addView(child, index, params);

}

注1:View类也提供了两个静态方法,作用一样

View.inflate(int resource, ViewGroup root);

View.inflate(int resource, ViewGroup root, boolean attachToRoot);

三 Demo演示

以后遇到inflate的布局文件的layout属性失效,我想大家应该知道什么原因了。

理论上应该写个demo演示的,其实demo已写好,就是不想截图了。这里就偷懒用ListView的item的布局举个例子,我想大家写Adapter应该很熟悉了。

item.xml

android:layout_width="match_parent"

android:layout_height="60dip"

android:gravity="center_vertical"

android:orientation="horizontal">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="test" />

Adapter

public View getView(int position, View convertView, ViewGroup parent) {

if (convertView == null) {

convertView = inflate(R.layout.item, null);

}

return convertView;

}

这样写,android:layout_height的60dip失效了,对不对。

换成下面:

public View getView(int position, View convertView, ViewGroup parent) {

if (convertView == null) {

convertView = inflate(R.layout.item, parent,false);

}

return convertView;

}

是不是60dip生效了。

算了再贴个Demo吧,图就不贴了。

activity xml

android:id="@+id/root_view"

android:layout_width="match_parent"

android:layout_height="match_parent">

inflate view

android:layout_width="100dp"

android:layout_height="100dp"

android:orientation="vertical"

android:text="test"/>

activity:部分代码需要注释

//情况1

View inflateView = getLayoutInflater().inflate(R.layout.inflate_test, null);

//情况2

View inflateView = getLayoutInflater().inflate(R.layout.inflate_test, null);

rootView.addView(inflateView);

//情况3

View inflateView = getLayoutInflater().inflate(R.layout.inflate_test, rootView,false);

//情况2

View inflateView = getLayoutInflater().inflate(R.layout.inflate_test, rootView,false);

rootView.addView(inflateView);

//情况4

View inflateView = getLayoutInflater().inflate(R.layout.inflate_test, rootView,true);

java layoutinflater_LayoutInflater详解相关推荐

  1. Apache Thrift - java开发详解

    2019独角兽企业重金招聘Python工程师标准>>> Apache Thrift - java开发详解 博客分类: java 架构 中间件 1.添加依赖 jar <depen ...

  2. Java泛型详解-史上讲解最详细的,没有之一

    目录 1. 概述 2. 一个栗子 3. 特性 4. 泛型的使用 4.1 泛型类 4.2 泛型接口 4.3 泛型通配符 4.4 泛型方法 4.4.1 泛型方法的基本用法 4.4.2 类中的泛型方法 4. ...

  3. Java虚拟机详解----JVM常见问题总结

    [正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考本人之前的系列文章,尤其是那篇:Java虚拟机详解04----GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾 ...

  4. java 泛型详解、Java中的泛型方法、 java泛型详解

    本文参考java 泛型详解.Java中的泛型方法. java泛型详解 概述 泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用. 什么是泛型?为什么要使用泛型? 泛型,即& ...

  5. 最详细的java泛型详解

    来源:最详细的java泛型详解 对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下. 本文参考java 泛型详解.Java中的泛型方法. ja ...

  6. Java异常详解及如何处理

    来源:Java异常详解及如何处理 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言 ...

  7. Java基础——Java NIO详解(一)

    一.基本概念 1.I/0简介 I/O即输入输出,是计算机与外界世界的一个借口.IO操作的实际主题是操作系统.在java编程中,一般使用流的方式来处理IO,所有的IO都被视作是单个字节的移动,通过str ...

  8. Java基础——Java NIO详解(二)

    一.简介 在我的上一篇文章Java NIO详解(一)中介绍了关于标准输入输出NIO相关知识, 本篇将重点介绍基于网络编程NIO(异步IO). 二.异步IO 异步 I/O 是一种没有阻塞地读写数据的方法 ...

  9. Java基础——Java IO详解

    一.概述 1.Java IO Java IO即Java 输入输出系统.不管我们编写何种应用,都难免和各种输入输出相关的媒介打交道,其实和媒介进行IO的过程是十分复杂的,这要考虑的因素特别多,比如我们要 ...

  10. packageinfo.java_package-info.java文件详解

    package-info.java文件详解 一.pacakge-info.java介绍 pacakge-info.java是一个Java文件,可以添加到任何的Java源码包中.pacakge-info ...

最新文章

  1. pycuda write complex numbers — errors:class “cuComplex” has no member “i”
  2. OVS DPDK--介绍(二)
  3. geoserver加载mysql_GeoServer+MySQL的配置过程
  4. 【若依(ruoyi)】模态框
  5. [JavaWeb-Servlet]概述与快速入门
  6. TP框架如何绑定参数。目的进行ajax验证
  7. Gensim word2vec计算多个词之间的相似度
  8. 必看!程序员逃生指南!
  9. python快速开发 数据管理网站_GitHub - AngelLiang/kingWeb: Python django后台快速开发框架...
  10. springboot-admin对springboot项目监控
  11. c# 设为首页和加入收藏代码
  12. 为什么面向对象糟透了?
  13. UnityShader学习——非真实感渲染
  14. 「萌新上手Mac」安装软件,步骤超简单
  15. 如何优雅的修改 Kubernetes Master 节点 IP?可没你想象中那么简单!
  16. iOS开发适配iPhone X 齐刘海处理,代码适配iPhoneX
  17. windows安装Rocket因为JAVAHOME空格导致找不到加载类问题
  18. 推荐测试网站的性能测试工具这最佳的12款
  19. html怎么去除广告,无需外力 巧妙去除Vagaa哇嘎界面广告
  20. 自动花洒嵌入式c语言程序设计教程课后答案,PS-金属花洒精修

热门文章

  1. mysql pxc 使用_MySQL PXC集群安装配置
  2. 信息学奥赛一本通(C++版)在线评测系统 1157:哥德巴赫猜想
  3. 5G垂直领域:华为智慧园区
  4. 计算机信息安全认识实习报告
  5. Java中实例是什么意思?补充:new 一个对象是实例吗? 能举个小例子吗?
  6. 计算机毕业设计ssm毕业论文管理系统b909r系统+程序+源码+lw+远程部署
  7. ERP系统功能之生产管理
  8. MPEG-2 TS学习(一)MPEG-2 TS格式解析
  9. 矩形口径喇叭天线设计——参数设置
  10. 华中科技大学伍冬睿教授团队关于生理计算中的对抗攻击与防御综述