问题
I am getting this error but I am not sure exactly why:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
The part where I add the View is the line that the error is pointing to. I am providing my Adapter code in order for you guys to get a better picture of what I am doing and why I am getting this error. Please let me know if anymore info is needed. Thanks in advance.
Adapter
private class InnerAdapter extends BaseAdapter{
String[] array = new String[] {"12\nAM","1\nAM", "2\nAM", "3\nAM", "4\nAM", "5\nAM",
"6\nAM", "7\nAM", "8\nAM", "9\nAM", "10\nAM", "11\nAM",
"12\nPM", "1\nPM", "2\nPM", "3\nPM", "4\nPM", "5\nPM",
"6\nPM", "7\nPM", "8\nPM", "9\nPM", "10\nPM", "11\nPM"};
TextView[] views = new TextView[24];
public InnerAdapter() {
TextView create = new TextView(DayViewActivity.this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 62, getResources().getDisplayMetrics()), 1.0f);
params.topMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
params.bottomMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
create.setLayoutParams(params);
create.setBackgroundColor(Color.BLUE);
create.setText("Test");
views[0] = create;
for(int i = 1; i < views.length; i++) {
views[i] = null;
}
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return array.length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
convertView = inflater.inflate(R.layout.day_view_item, parent, false);
}
((TextView)convertView.findViewById(R.id.day_hour_side)).setText(array[position]);
LinearLayout layout = (LinearLayout)convertView.findViewById(R.id.day_event_layout);
if(views[position] != null) {
layout.addView((TextView)views[position], position);
}
return convertView;
}
}
XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="61dp"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="61dp"
android:orientation="vertical">
<TextView
android:id="@+id/day_hour_side"
android:layout_width="wrap_content"
android:layout_height="60dp"
android:text="12AM"
android:background="#bebebe"
android:layout_weight="0"
android:textSize="10dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_weight="0"
android:background="#000000"
android:id="@+id/hour_side_divider"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="61dp"
android:orientation="vertical"
android:layout_weight="1">
<LinearLayout
android:id="@+id/day_event_layout"
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal" ></LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000000"
android:id="@+id/event_side_divider" />
</LinearLayout>
</LinearLayout>
回答1:
You didn't say when you get that exception(when the application starts or when you scroll the GridView
up and down) but it's normal. The views
array has one value that is not null
(the first entry in that array in set to the TextView
that you create) and most likely you'll be trying to re-add that TextView
at some point. Also the parent AdapterView
may call the getView
method several times to get some children to measure.
Anyway you don't know exactly what you're trying to do but the current approach is wrong.
First, you create an array with one TextView
and the rest of the values set to null
and you basically don't do anything else with it(but maybe this isn't the full code?!). Second, you shouldn't store an array of Views
especially within a child of AdapterView
(like GridView
, ListView
etc) which has a mechanism to recycle its children. Third, you didn't take in consideration the recycling mechanism of the GridView
. For example, you add the TextView
for the first element but you don't revert this changes in the getView
so if this first row's View
(which contains the added TextView
) gets recycled you'll end up with a row View
containing the previously added TextView
at rows where you don't want it.
回答2:
I already accepted an answer, but thought I'd add this as it helps explain some stuff about ListView
(and by definition, GridView as well), that someone learning about it can understand. I was confused about recycling Views in ListView, and this article I found is great. Explains it well. Hopefully it helps anyone not fully understanding how ListView and Adapters work, which was an obvious problem for me.
来源:https://stackoverflow.com/questions/11919033/why-do-i-need-to-call-removeview-in-order-to-add-a-view-to-my-linearlayout