LayoutInflater.inflater()方法就是根据一个xml文件来生成一个view对象,注意跟getviewbyid的区别,后者是从view独享中找到指定的控件。
在LayoutInflater中对inflater()有四种重载分别是
- public View inflate(int, ViewGroup)
- public View inflate(XmlPullParser, ViewGroup)
- public View inflate(int, ViewGroup, boolean)
- public View inflate(XmlPullParser, ViewGroup, boolean)
好的,老规矩上源码,不用看懂,哥们后面会帮你简化的,
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();
}
}
得到的答案是根据resource初始化视图后调用4号方法
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 xml
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 supplied
params = 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;
}
}
眼疼不?疼的话咱们看简化版本的
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
synchronized (mConstructorArgs) {
//第一步:初始化
final AttributeSet attrs = Xml.asAttributeSet(parser);
Context lastContext = (Context)mConstructorArgs[0];
mConstructorArgs[0] = mContext;
//注意这里,在初始化时,result表示要返回的视图,默认是返回root
View result = root;
…………
final String name = parser.getName();
//第二步:创建XML对应的空白VIEW:temp
if (TAG_MERGE.equals(name)) {
//如果是merge标签:抛出异常 (因为merge标签能够将该标签中的所有控件直接连在上一级布局上面,从而减少布局层级,假如一个线性布局替换为merge标签,那么原线性布局下的多个控件将直接连在上一层结构上,也就是如果加载进来的root根节点是root的话,那么将来无法知道布局的根节点是什么)
…………
} else {
View temp;
if (TAG_1995.equals(name)) {
temp = new BlinkLayout(mContext, attrs);
} else {
temp = createViewFromTag(root, name, attrs);
}
//第三步:从根结点中,获取布局参数,设置到temp中
ViewGroup.LayoutParams params = null;
if (root != null) {
// Create layout params that match root, if supplied
params = 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);
}
}
//第四步:初始化temp中的子控件
rInflate(parser, temp, attrs, true);
//第五步:如果root不为空,而且attachToRoot设为TRUE,则将其视图通过addView添加到root中
if (root != null && attachToRoot) {
root.addView(temp, params);
}
//第六步:如果root为空,或者attachToRoot设为FALSE,那么就将TEMP视图做为result返回
if (root == null || !attachToRoot) {
result = temp;
}
}
return result;
}
}
看到这里咱们就可以进入正题了 每个参数是社么意思?
public View inflate(int resouce, ViewGroup root, boolean attachToRoot)
- 第一个参数 生成temp,注意这里的temp不一定是inflate这个方法返回的view奥
- root 父布局 为temp提供参数,如果没有temp默认是wrap_content
- attachToRoot是否调用addview添加到父布局
使用过程中出现的问题总结
总结一下adapter的getview中出现的问题
一,在item根布局中,明明定义了match或者200dp,但是item还是wrap_content,
看看你调用的是不是nflate(resouce, null)’因为这里没有传入父布局所以无法为temp添加跟节点所需要的参数,(不添加参数怎么了?老子定义了match了!),您定义的在初始化temp的时候系统没加进去,谢谢
正确的方法是nflate(resouce, root,false)
(老子就不,你让我false 我就弄个true)
true的意思基本和
listview。add(item);
然后把listview返回差不多
报错没有 这里的root相当于是listview 你listview。add(item)不出错吗?
为什么我nflate(resouce, null)出来的额itemview也正常呢
因为你的itemview中的子控件已经把它给撑大了, - -