博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
安卓java.lang.IllegalStateException: The specified child already has a parent.解决方案
阅读量:6401 次
发布时间:2019-06-23

本文共 3811 字,大约阅读时间需要 12 分钟。

在使用ViewPager的时候遇到一个错误java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.。经过多次调试及网上查找相关资料,终于弄明白是咋回事,现记录如下:

首先跟大家讲解一下为何会出现该错误,然后再提供自己的错误代码分析错误原因及解决方案。

一为何会报java.lang.IllegalStateException: The specified child already has a parent.错误

根据The specified child already has a parent. You must call removeView() on the child's parent first.的字面意思是一个子View已经存在一个父View,你必须先调用该子视图的父视图的 removeView() 方法,这种情况通常出现在动态添加视图的情况下,出现这种错误的原因是一个子控件只允许存在一个父控件,而很多时候在动态添加视图的时候,我们不知道该子视图是否已存在父视图,当已存在的时候就会报错。

二错误代码分析错误及解决方案:

出错的代码主要是在ViewPager的适配器类的instantiateItem方法中,因为在该方法中我们通常会动态的添加视图。在自己的项目的主界面中定义了一个ViewPager用来循环显示多个GridView,而在主界面中GridView是通过LayoutInflater来动态获取的,代码如下:

LayoutInflater inflater=getActivity().getLayoutInflater();		View view=inflater.inflate(R.layout.viewpager,null);		campanyGridView=(GridView) view.findViewById(R.id.campany_gridview_1);
然后将多个campanyGridView添加到List集合中,然后将该ArrayList集合对象作为参数传递给ViewPager对应的Adapter,代码如下:

public class ViewPaperAdapter extends PagerAdapter {	private ArrayList
viewList; public ViewPaperAdapter(ArrayList
viewList) { // TODO Auto-generated constructor stub this.viewList=viewList; } @Override public void destroyItem(ViewGroup container, int position, Object object) { // TODO Auto-generated method stub //super.destroyItem(container, position, object); container.removeView(viewList.get(position)); } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(viewList.get(position)); return viewList.get(position); } @Override public int getCount() { // TODO Auto-generated method stub return viewList.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub return arg0==arg1; } }
其中PagerAdapter中的instantiateItem方法是用来显示我们添加的视图控件的,其中视图对应的R.layout.viewpager的XML文件如下:

布局很简单,只是在LinearLayout中放了一个GridView控件而已。但是当点击自己项目APP的底部导航按钮(界面类似QQ)来切换界面时报错,即java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.。通过我们上述讲解大家应该能够明白为何出错。

错误分析:因为ViewPager的视图的显示是在PagerAdapter中通过instantiateItem方法来动态添加的,通常我们在该方法中会调用container.addView(viewList.get(position));来添加一个视图,即调用ViewGroup的addView来动态添加控件,但是可以看到在我们的R.layout.viewpager的XML文件中GridView的外部是LinearLayout布局控件,即此时GridView的父控件为LinearLayout,这样就相当于把一个以存在父控件的子控件动态的添加到一个ViewGroup容器中,这是不被允许的,因为一个子控件只允许存在一个父容器控件,因此会报错。

解决方案:通过上述的分析可以很容易找到解决方案:

1去除R.layout.viewpager的XML文件中GridView的外部的LinearLayout布局控件,这样GridView就不存在父容器控件。

2在在PagerAdapter中通过instantiateItem方法中动态添加视图前做一个简单的判断,判断待添加的视图是否已存在父控件,若存在则调用removeAllViews()去除之。代码如下:

public Object instantiateItem(ViewGroup container, int position) {		// TODO Auto-generated method stub		View v=viewList.get(position);		ViewGroup parent = (ViewGroup) v.getParent();		//Log.i("ViewPaperAdapter", parent.toString());		if (parent != null) {		parent.removeAllViews();		}		container.addView(viewList.get(position));		return viewList.get(position);	}
可以看到第一种方案简单粗暴,但适用性不强,因为我们要添加的一个视图可能很复杂,而不是一个简单的GridView,那么我们必须使用类似LinearLayout的基本布局控件来控制我们的视图,因此第二种方案很显然适用此种情况。

三总结:

ViewGroup的addView()方法不能添加一个已存在父控件的视图,因此在使用类似ViewPager的控件动态添加视图时,要在addView前先判断再添加,上述案例可以扩展为不能使用addView()对同一个控件动态添加两次,因为第一个添加时已表示该子控件已存在父容器控件,第二次添加时尽管其父容器控件是同一个控件,但是相当于该子视图已存在父容器控件,因此仍会报错,如下代码是错误的:

private void initView() {        LinearLayout viewGroup = (LinearLayout) findViewById(R.id.main_activity_linearlayout);        LayoutInflater inflater = LayoutInflater.from(this);        View textView = inflater.inflate(R.layout.test, null);        viewGroup.addView(textView);        viewGroup.addView(textView);     //这个地方出错,不能对其添加两次。    }
解决方案也很简单,对于添加的第二个视图,重新用一个布局文件定义,然后通过inflater.inflate获取再动态添加。

转载于:https://www.cnblogs.com/hainange/p/6334020.html

你可能感兴趣的文章
MySql Blob图片类型存储Bug解决:索引超出了数组界限错误
查看>>
enum枚举类型
查看>>
Android API 中文 (52) —— ZoomButtonsController.OnZoomListener
查看>>
Go语言的可变(不定长)参数函数
查看>>
!+"\v1" 用来“判断浏览器类型”还是用来“IE判断版本”的问题!
查看>>
Linux IO模型漫谈(2)
查看>>
[网摘学习]在Ubuntu上安装和配置OpenStack Nova之二
查看>>
想挖大数据价值,你得先“挖人”!
查看>>
core dump磁盘报警问题排查过程
查看>>
Nginx报 No input file specified. 的问题解决之路
查看>>
Design Pattern: Not Just Mixin Pattern
查看>>
Ubuntu14.04下安装Hadoop2.5.1 (单机模式)
查看>>
kettle入门与实战(视频教程)
查看>>
简单JNI使用demo
查看>>
框架开发管理流程图
查看>>
Java 容器 & 泛型:四、Colletions.sort 和 Arrays.sort 的算法
查看>>
GDB的两个技巧
查看>>
PHP MysqlND 简介
查看>>
iOS面试题
查看>>
使用JavaIO提供的API下载指定文件(image)
查看>>