RecyclerView遇到的一个坑,item.xml的layout属性失效,阅读源码了解坑的原理

  • 前言
  • 遇坑代码
  • inflate源码分析

前言

我们都知道,使用RecyclerView时,需要填充一个item.xml。但是我运行程序员后,发现item.xml的根View的layout属性没有生效,解决办法就是将inflate(R.layout.item,null)改成inflate(R.layout.item,parent,false)。决解问题后并不满足,想看一看源码了解产生这个坑的原因。

遇坑代码

 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
     return new Viewholder(inflater.inflate(R.layout.item,null));
 }

R.layout.item代码


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:padding="10dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:textColor="#ffff"
            android:text="aaaaaaaaaaaaa"/>
LinearLayout>

LinearLayout的layout属性失效。

inflate源码分析

为什么将inflate(R.layout.item,null)改成inflate(R.layout.item,parent,false)就好了呢?这里最关键的时前者root参数是空。后者是parent,不为空。我们看源码比较一下这两个的差别。

三个参数的inflate
public View inflate (int resource, ViewGroup root, boolean attachToRoot)
两个参数的inflate
public View inflate (int resource, ViewGroup root)

作用:将xml布局文件实例化为它对应的View对象

两个参数和三个参数的源码一样,两个参数的会转化成三个参数的。
public View inflate(XmlPullParser parser, @Nullable ViewGroup root) {
        return inflate(parser, root, root != null);
    }

源码(这里只截取关键部分):

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
    final AttributeSet attrs = Xml.asAttributeSet(parser);

    final String name = parser.getName();//获取根view的名字

    final View temp = createViewFromTag(root, name, inflaterContext, attrs);//temp是xml的根view,也就是最外层的ViewGroup。我们所说的layout属性失效,也是指这个view。

    if (root != null) { //这两个的差别主要在这里
         params = root.generateLayoutParams(attrs);//生成LayoutParams
         if (!attachToRoot) {
             temp.setLayoutParams(params);//设置LayoutParams
         }
     }

    rInflateChildren(parser, temp, attrs, true);//实例化temp的所有子view

    if (root == null || !attachToRoot) {
        result = temp;
    }

    return result;//返回实例化后的view

}           

看到这里大家应该明白了,不获取LayoutParams,Layout属性当然就没用了。

你可能感兴趣的:(android,源码)