Почему мне нужно вызвать removeView(), чтобы добавить View в мой LinearLayout
Я получаю эту ошибку, но я точно не знаю, почему:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child parent first.
Часть, где я добавляю View, - это строка, на которую указывает ошибка. Я предоставляю свой код адаптера, чтобы вы, ребята, могли лучше понять, что я делаю, и почему я получаю эту ошибку. Пожалуйста, дайте мне знать, если больше информации не требуется. Спасибо заранее.
Адаптер
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
Вы не сказали, когда получите это исключение (когда приложение запускается или когда вы прокручиваете GridView
вверх и вниз), но это нормально. Массив views
имеет одно значение, которое не является null
(первая запись в этом массиве в параметре TextView
, который вы создаете), и, скорее всего, вы попытаетесь повторно добавить этот TextView
в некоторые точка. Кроме того, родительский AdapterView
может несколько раз вызвать метод getView
, чтобы определить некоторые дочерние элементы.
В любом случае вы не знаете точно, что вы пытаетесь сделать, но текущий подход неверен.
Сначала вы создаете массив с одним TextView
, а остальные значения равны null
, и вы в основном ничего не делаете с ним (но, возможно, это не полный код?!). Во-вторых, вы не должны хранить массив views
, особенно в дочернем элементе AdapterView
(например, GridView
, ListView
и т.д.), Который имеет механизм для регенерации своих детей. В-третьих, вы не учли механизм рециркуляции GridView
. Например, вы добавляете TextView
для первого элемента, но вы не возвращаете эти изменения в getView
, поэтому, если эта первая строка View
(содержащая добавленный TextView
) будет переработана, вы в конечном итоге с строкой View
, содержащей ранее добавленную TextView
в строках, где вы ее не хотите.
Ответ 2
Я уже принял ответ, но подумал, что добавлю это, поскольку он помогает объяснить некоторые вещи о ListView
(и по определению, GridView), что кто-то узнает об этом, может понять. Я был смущен переработкой Views в ListView, и this, которую я нашел, замечательно. Объясняет это хорошо. Надеюсь, это поможет любому, кто не в полной мере понимает, как работают ListView и Adapters, что явилось для меня очевидной проблемой.