由于经常会使用
View view = inflater.inflate(R.layout.fragment_main, container, false); 或者
View view = inflater.inflate(R.layout.dialog_kp_user_product_item, null);
两个方法,但是不知道其有什么区别?如果搞错了会报
Caused by: java.lang.IllegalStateException:The specified child already has a parent. You must call removeView() on the child's parent first.
比如说我们在adapter ,把第三个参数改为true, 在动态添加布局的时候把 null 改为容器view,这样就会出现上面的错误?原因是传了true,表示立即把view 添加到viewGroup中,后面adapter 会再次把view 添加到viewGroup,这时候就会报错说 illegalStateException, 因为view已经被添加了,不能再次被添加。同理,对于
View view = inflater.inflate(R.layout.dialog_kp_user_product_item, null);
也是如此,该方法一般再动态添加布局的时候用到,比如在动态添加布局时候,我们会用到此方法
public void setLayout(View view){
View subLayout = LayoutInflater.from(this).inflate(R.layout.sub_layout, null);
mLinearLayout.addView(subLayout);
}
这里第二个参数传了null,源码追寻,
public void addView(View child, int index) {
if (child == null) {
throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
}
LayoutParams params = child.getLayoutParams();
if (params == null) {
params = generateDefaultLayoutParams();
if (params == null) {
throw new IllegalArgumentException("generateDefaultLayoutParams() cannot return null");
}
}
addView(child, index, params);
}
public void addView(View child, int index, LayoutParams params) {
if (DBG) {
System.out.println(this + " addView");
}
if (child == null) {
throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup");
}
// addViewInner() will call child.requestLayout() when setting the new LayoutParams
// therefore, we call requestLayout() on ourselves before, so that the child's request
// will be blocked at our level
requestLayout();
invalidate(true);
addViewInner(child, index, params, false);
}
点击addView,往下走,会看到 addView (View child, int index, LayoutParams params),添加之前会测量一遍,在刷新,最后add,我们点进去addViewInner ,
private void addViewInner(View child, int index, LayoutParams params,
boolean preventRequestLayout) {
if (mTransition != null) {
// Don't prevent other add transitions from completing, but cancel remove
// transitions to let them complete the process before we add to the container
mTransition.cancel(LayoutTransition.DISAPPEARING);
}
if (child.getParent() != null) {
throw new IllegalStateException("The specified child already has a parent. " +
"You must call removeView() on the child's parent first.");
}
if (mTransition != null) {
mTransition.addChild(this, child);
}
if (!checkLayoutParams(params)) {
params = generateLayoutParams(params);
}
......... 省略后面代码
重点来了,if (child.getParant () != null) 时候抛出一个异常,而内容就是我们刚刚报的异常;这样我们就明白了。inflater.inflate(R.layout.fragment_main, container, false)
打包 inflate 布局的时候不能立即给view添加父布局,否则会抛出异常。注意,这里的表述不能立即给view添加父布局,不是不添加,第三个参数 false 表示 延后添加,true 表示立即添加;同理,inflater.inflate(R.layout.dialog_kp_user_product_item, null);
第二个参数为空自然没有父view ,也就不存在添加一说,当调用root.addView(subLayout)时候,root 会直接添加的,所以这里就不应该再传一个容器view,否则会重复添加,在调用addView的时候就会出错。
总结:一般,添加view的职责是系统做的,当我们调用addView的时候,这个添加任务系统就会帮我们做掉。我们仅仅是需要提供一个view 布局,通过inflate 实现,但是inflater 也能够帮忙添加布局,所以在inflater 就不需要添加布局了。
个人愚见,如有不正,欢迎指出。