“The specified child already has a parent”异常分析(由于addView方法产生)

来源:互联网 发布:sql in和not in的用法 编辑:程序博客网 时间:2024/06/16 14:30

最近在写一个VewPager的时候,遇到了这样的一个异常:

java.lang.IllegalStateException The specified child already has a parent. You must call removeView() on the child's parent first.

找到错误代码如下:

//imageViews是图片集合List<ImageView> imageViews = new ArrayList<String>();ImageView imageView = new ImageView(this);//imageId[]是image集合的id,遍历数组将imageView加入myViewPager中for(int i=0; i<imageId.length; i++){imageView.setBackgroundResource(imageId[i]);myViewPager.addView(imageView);}

报了这个错误后,字面意思是:这个指定的孩子已经有一个父亲了,你必须从孩子的父亲移除这个孩子。

没有怎么理解这句话,但是在debug的过程中,我发现imageViews中的元素是相同的。

于是我将代码改成了如下:

//imageViews是图片集合List<ImageView> imageViews = new ArrayList<String>();ImageView imageView = null;//imageId[]是image集合的id,遍历数组将imageView加入myViewPager中for(int i=0; i<imageId.length; i++){imageView = new ImageView(this);imageView.setBackgroundResource(imageId[i]);myViewPager.addView(imageView);}
在遍历数组的时候,每次new一个新的imageView,代码就运行通过了。

于是明白了,问题出在不能将一个view重复添加


接着写了一个demo来验证这个问题:

TextView tv = new TextView(this);tv1.setText("我是添加的元素");LinearLayout myLinearLayout = (LinearLayout) findViewById(R.id.ll);//添加同一个view,结果报错myLinearLayout.addView(tv1);

将这段代码运行后,果然报了“The specified child already has a parent”这个错误。

验证了果然不能讲同一个view添加两次。


回到提示中,“这个指定的孩子已经有一个父亲了,你必须从孩子的父亲移除这个孩子”

xxx.addView(yyy),显然yyy是xxx的孩子

那么再次运行xxx.addView(yyy)这个代码的时候,因为xxx已经有了父亲(yyy),就不能再次认yyy做父亲了吗?


接下来写了两个父亲来接受同一个孩子,来验证这个问题:

TextView tv = new TextView(this);tv.setText("我是text");LinearLayout ll1 = (LinearLayout) findViewById(R.id.ll_1);LinearLayout ll2 = (LinearLayout) findViewById(R.id.ll_2);ll1.addView(tv);ll2.addView(tv);
运行了这段代码后,仍然报了“The specified child already has a parent”这个错误。

从父控件来看:第一次addView的时候,ll1有了tv这个孩子。如果ll1没有移除tv这个孩子,ll2将不能拥有这个孩子。

从子控件来看:第一次addView的时候,tv有了ll1这个爹。如果tv没有和ll1断绝关系,tv将不能认ll2为爹。


说明不能将一个view重复添加有两种情况:

不能将一个view重复添加给同一个父view,也不能将一个view重复添加给不同的view。一个view只能属于某一个父view。


得出了结论:

对于parentView.addView(childView)这个方法而言,重点是childView这个方法是将childView这个子控件填入parentView中,产生了父子关系。(就是childView认爹的过程)

在一个childView认了爹(属于某个父控件)之后,想要运行otherParentView.addView(childView)时(也就是childView这死娃子又要认别人爹了),首先要和第一个爹断绝关系(parentView.remove(childView)),才可以认第二个爹。

如果第一个爹还没断了关系,又要认第二个爹,就会报出"The specified child already has a parent"这个错误。

0 0