奔溃日志:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
奔溃分析:
由奔溃日志看出是奔溃的原因是一个子View已经存在一个父View,我在添加这个子view的时候需要先从他的父View中移除,因为一个view只能有一个父View。这种情况通常出现在动态添加视图的情况下,出现这种错误的原因是一个子控件只允许存在一个父控件,而很多时候在动态添加视图的时候,我们不知道该子视图是否已存在父视图,当已存在的时候就会报错。
问题查找:
ViewPager的适配器类中添加View的方法是instantiateItem。我的项目中是这样写的。
我使用DataBindingUtil来获取一个ItemView。
ItemVideoBinding binding = DataBindingUtil.inflate(LayoutInflater.from(this.mContext), R.layout.item_video, container, true);
接下来看下上面四个参数的作用:
第一个是inflater 第二个是layoutId。这两个的作用就的通过这个方法将xml布局文件实例化为inflater对应的View对象。LayoutInflater这个类是不能直接使用的,也就是不能直接调用其中的成员。一般,我们通过getLayoutInflater()方法或者 getSystemService(String)方法来获得该类的实例,通过以上两个方法获得的LayoutInflater类实例,已经和当前的上下文关联起来,并且已经正确配置在当前程序运行的设备上。
第三个参数parent 表示父类容器,当第四个参数 attachToParent 为true时,表示将子view添加到这个父类容器中。当attachToRoot为false的时候,parent就是一个普通的view,用来帮助决定inflate方法返回view的LayoutParams。即parent会协助linearlayout的根节点生成布局参数,只有这一个作用。View的绘制流程中,子view的大小是由父view的measurespec和子view的宽高值决定的。
当第三个参数parent为null时, attachToParent 设置为true是没有意义的。所以我上面的代码会将前面的布局添加到第三个参数parent 这个viewfGroup中,这个时候这个Item就已经有一个父View了。代码的最后我再使用container.addView 将子View添加进来,就报了上面这个错误。
解决方案:
将DataBindingUtil.inflate方法改为
ItemVideoBinding binding = DataBindingUtil.inflate(LayoutInflater.from(this.mContext), R.layout.item_video, null, false);
即可以解决问题。
关于LayoutInflater中inflate方法中三个参数的作用,可以参考
三个案例带你看懂LayoutInflater中inflate方法两个参数和三个参数的区别