inflater.inflate()参数详解
前言
今天在lint项目的代码时,又遇到了inflate方法的参数问题,之前看过相关的文章,又没有记录下来,导致时间长了就忘记了。今天再次遇到这个问题,便老老实实记录一下LayouInflater中inflate方法两个参数和三个参数的区别。
用法
LayoutInflater.from(RecylerActivity.this).inflate(R.layout.my_text_view,viewGroup,false);View.inflate(RecylerActivity.this, R.layout.my_text_view, null);
通过看源码得知View.inflate()方法实际上调用的也是LayoutInflater.from(int resource, ViewGroup root, boolean attachToRoo);
区别
我们最常用的便是LayoutInflater的inflate方法,这个方法重载了四种调用方式,分别为:
1. public View inflate(int resource, ViewGroup root)2. public View inflate(int resource, ViewGroup root, boolean attachToRoot)3. public View inflate(XmlPullParser parser, ViewGroup root)4. public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)
这四种使用方式中,我们最常用的是第一种方式,inflate方法的主要作用就是将xml转换成一个View对象,用于动态的创建布局。虽然重载了四个方法,但是这四种方法最终调用的,还是第四种方式。第四种方式也很好理解,内部实现原理就是利用Pull解析器,对Xml文件进行解析,然后返回View对象。
inflate方法有三个参数,分别是
1.resource 布局的资源id
2.root 填充的根视图
3.attachToRoot 是否将载入的视图绑定到根视图中
我们经常使用的第一种形式为例,你在重写BaseAdapter的getView方法的时候是否这样做过
public View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = inflate(R.layout.item_row, null);}return convertView;
}
我们将root参数设为空,功能确实实现了,但是这里还隐藏着一个隐患,这种方式并不是inflate正确的使用姿势,下面我们通过一个Demo,来说一下这样使用造成的弊端。
对应的布局文件如下
<!--?xml version="1.0" encoding="utf-8"?--><linearlayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="60dp"android:background="@android:color/holo_orange_light"android:gravity="center"android:orientation="vertical"><textviewandroid:id="@+id/tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="11"android:textcolor="@android:color/black"android:textsize="22sp"></textview></linearlayout>
OneActivity的代码如下
public class OneActivity extends Activity {private ListView list1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_one);list1 = (ListView) findViewById(R.id.list1);list1.setAdapter(new MyAdapter(this));}private class MyAdapter extends BaseAdapter {private LayoutInflater inflater;MyAdapter(Context context) {inflater = LayoutInflater.from(context);}@Overridepublic int getCount() {return 20;}@Overridepublic Object getItem(int position) {return position;}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = inflater.inflate(R.layout.item_list, null);}TextView tv = (TextView) convertView.findViewById(R.id.tv);tv.setText(position+"");return convertView;}}}
TwoActivity的代码如下
public class TwoActivity extends Activity {private ListView list2;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_two);list2 = (ListView) findViewById(R.id.list2);list2.setAdapter(new MyAdapter(this));}private class MyAdapter extends BaseAdapter {private LayoutInflater inflater;MyAdapter(Context context) {inflater = LayoutInflater.from(context);}@Overridepublic int getCount() {return 20;}@Overridepublic Object getItem(int position) {return position;}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = inflater.inflate(R.layout.item_list, parent,false);}TextView tv = (TextView) convertView.findViewById(R.id.tv);tv.setText(position + "");return convertView;}}}
两个文件最关键的区别就一句话,
在getView方法中,OneActivity是
convertView = inflater.inflate(R.layout.item_list, null);
在getView方法中,TwoActivity是
convertView = inflater.inflate(R.layout.item_list, parent,false);
我们先看一下显示效果,再说两者的区别
OneActivity效果
TwoActivity的显示效果
我们可以很明显的看出来,使用第一种方式,根布局的高度设置60dp没有起作用,系统还是按照包裹内容的方式加载的,为什么会产生这种效果呢?我们从需要inflate方法的源代码中找一下答案。
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {return inflate(resource, root, root != null);}
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();}}
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {synchronized (mConstructorArgs) {Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");final Context inflaterContext = mContext;final AttributeSet attrs = Xml.asAttributeSet(parser);Context lastContext = (Context) mConstructorArgs[0];mConstructorArgs[0] = inflaterContext;View result = root;try {// Look for the root node.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!");}final String name = parser.getName();if (DEBUG) {System.out.println("**************************");System.out.println("Creating root view: "+ name);System.out.println("**************************");}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, inflaterContext, attrs, false);} else {// Temp is the root view that was found in the xmlfinal View temp = createViewFromTag(root, name, inflaterContext, attrs);ViewGroup.LayoutParams params = null;if (root != null) {if (DEBUG) {System.out.println("Creating params from root: " +root);}// Create layout params that match root, if suppliedparams = root.generateLayoutParams(attrs);if (!attachToRoot) {// Set the layout params for temp if we are not// attaching. (If we are, we use addView, below)temp.setLayoutParams(params);}}if (DEBUG) {System.out.println("-----> start inflating children");}// Inflate all children under temp against its context.rInflateChildren(parser, temp, attrs, true);if (DEBUG) {System.out.println("-----> done inflating children");}// 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;}}} catch (XmlPullParserException e) {final InflateException ie = new InflateException(e.getMessage(), e);ie.setStackTrace(EMPTY_STACK_TRACE);throw ie;} catch (Exception e) {final InflateException ie = new InflateException(parser.getPositionDescription()+ ": " + e.getMessage(), e);ie.setStackTrace(EMPTY_STACK_TRACE);throw ie;} finally {// Don't retain static reference on context.mConstructorArgs[0] = lastContext;mConstructorArgs[1] = null;Trace.traceEnd(Trace.TRACE_TAG_VIEW);}return result;}}
重点关注下面的
final View temp = createViewFromTag(root, name, inflaterContext, attrs);ViewGroup.LayoutParams params = null;if (root != null) {if (DEBUG) {System.out.println("Creating params from root: " +root);}// Create layout params that match root, if suppliedparams = root.generateLayoutParams(attrs);if (!attachToRoot) {// Set the layout params for temp if we are not// attaching. (If we are, we use addView, below)temp.setLayoutParams(params);}}
这些代码的意思就是,当我们传进来的root参数不是空的时候,并且attachToRoot是false的时候,也就是上面的TwoActivity的实现方式的时候,会给temp设置一个LayoutParams参数。
// 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,并且第三个参数是false的时候,这个temp就被加入到了root中,并且把root当作最终的返回值返回了。而当我们设置root为空的时候,没有设置LayoutParams参数的temp对象,作为返回值返回了。
因此,我们可以得出下面的结论:
1.若我们采用convertView = inflater.inflate(R.layout.item_list, null);方式填充视图,item布局中的根视图的layout_XX属性会被忽略掉,然后设置成默认的包裹内容方式
2.如果我们想保证item的视图中的参数不被改变,我们需要使用convertView = inflater.inflate(R.layout.item_list, parent,false);这种方式进行视图的填充
3.除了使用这种方式,我们还可以设置item布局的根视图为包裹内容,然后设置内部控件的高度等属性,这样就不会修改显示方式了。
总之一句话,推荐用下边这种方式:
inflater.inflate(R.layout.item, parent, false);
另外本人还开设了个人公众号:JiandaoStudio ,会在公众号内定期发布行业信息,以及各类免费代码、书籍、大师课程资源。
扫码关注本人微信公众号,有惊喜奥!公众号每天定时发送精致文章!回复关键词可获得海量各类编程开发学习资料!
例如:想获得Python入门至精通学习资料,请回复关键词Python即可。
inflater.inflate()参数详解相关推荐
- android_基础_inflater.inflate()参数详解
前言 今天在lint项目的代码时,又遇到了inflate方法的参数问题,之前看过相关的文章,又没有记录下来,导致时间长了就忘记了.今天再次遇到这个问题,便老老实实记录一下LayouInflater中i ...
- inflater.inflate使用详解
原文地址:https://possiblemobile.com/2013/05/layout-inflation-as-intended/ Layout inflation is the term u ...
- LayoutInflater inflate参数详解
LayoutInflater 类概述: 实例化一个XML布局文件到相应的View对象,并不直接使用.使用getLayoutInflater()或getSystemService(String)来获取一 ...
- CI流水线配置文件参数详解(一)
文章目录 4. 参数详解(一) 4.1 ``script`` 4.2 ``image`` 指定使用Docker镜像.如 ``iamge:name`` ,暂时忽略. 4.3 ``before_scrip ...
- 内存性能参数详解(转载)
内存性能参数详解 先说说最有效提高你机器内存性能的几个参数:CL,TRP,TRCD CAS Latency "列地址选通脉冲潜伏期" BIOS中可能的其他描述为:tCL.CAS L ...
- spring boot 实战 / 可执行war启动参数详解
概述 上一篇文章<spring boot 实战 / mvn spring-boot:run 参数详解>主要讲解了spring boot 项目基于maven插件启动过程中借助profil ...
- 调包侠福音!机器学习经典算法开源教程(附参数详解及代码实现)
Datawhale 作者:赵楠.杨开漠.谢文昕.张雨 寄语:本文针对5大机器学习经典算法,梳理了其模型.策略和求解等方面的内容,同时给出了其对应sklearn的参数详解和代码实现,帮助学习者入门和巩固 ...
- plot参数详解python_30行Python代码实现3D数据可视化
作者:潮汐 来源:Python技术 欢迎来到编程教室~ 我们之前的文章中有讲解过不少 Matplotlib 的用法,比如: 完成这50个Matplotlib代码,你也能画出优秀的图表 25个常用Mat ...
- Ehcache配置参数详解
ehcache配置参数详解 <?xml version="1.0" encoding="UTF-8"?><ehcache><dis ...
最新文章
- 美国限制研究生入境,港大神操作,只要你愿意,填个表就行,还有机会获得校长奖学金...
- php document.write,在JS中有关document.write()的用法(详细教程)
- why header level note is disabled
- 如何在Visual Studio项目中正确添加汇编代码 .
- 使用Python实现生产者消费者问题
- Windows Server 2012 R2 VDI系列(四)—创建虚拟桌面集合
- mysql命令行闪退解决办法。
- Android 集成微信h5支付
- python实现银行ATM系统
- 51单片机矩阵按键模块
- 一键跳转添加QQ好友 点击链接直接跳转到QQ好友页面如何实现
- java excel 取消科学计数法_java使用poi解析或处理excel的时候,如何防止数字变成科学计数法的形式...
- solidity 重入攻击测试
- 选取销售订单开发票,控制销售订单中已开票金额
- cisco思科交换机恢复出厂设置清除配置的方法
- Tableau的特点和案例--可视化和交互化 和 其他
- 用光盘怎样重装电脑系统
- python爬虫爬拼多多销量_Python爬取各大汽车销量信息
- 1665. 计算数字
- 局域网屏幕共享_计算机:如何通过局域网方式接入Internet
热门文章
- 安卓巴士 http://www.apkbus.com/
- odata expand
- 选对用友BI解决方案 数据才能驱动成功
- 家用路由器-- LAN与WAN通信的过程以及IP转换
- STM32_时钟树原理图
- 自然语言处理——命名实体识别
- sencha touch 入门系列 (二)sencha touch 开发准备
- 如何借助new bing修复 pyfolio: AttributeError: ‘numpy.int64‘ object has no attribute ‘to_pydatetime‘
- 他人生的成功就是兑现自己此前的诺言
- 计算机硬件基础知识微课视频,《计算机硬件》微课及教学设计