Ответ 1
Сначала я также не знал об утилизации списков и механизме использования convertview, но после целого дня исследований я в значительной степени понимаю механизмы представления списков, ссылаясь на изображение из android.amberfog
Всякий раз, когда ваше представление списка заполняется адаптером, оно в основном показывает количество строк, которое список может отображать на экране, и количество строк не увеличивается даже при прокрутке списка. Это прием, который использует Android, чтобы listview работал более эффективно и быстро. Теперь, как вы можете видеть, внутренняя история просмотра списка, ссылающегося на изображение, первоначально у списка просмотра было 7 видимых элементов, затем, если вы прокрутите вверх, пока элемент 1 больше не будет виден, getView() передает это представление (т.е. item1) в переработчик и вы можете использовать
System.out.println("getview:"+position+" "+convertView);
внутри вашего
public View getView(final int position, View convertView, ViewGroup parent)
{
System.out.println("getview:"+position+" "+convertView);
ViewHolder holder;
View row=convertView;
if(row==null)
{
LayoutInflater inflater=((Activity)context).getLayoutInflater();
row=inflater.inflate(layoutResourceId, parent,false);
holder=new PakistaniDrama();
holder.tvDramaName=(TextView)row.findViewById(R.id.dramaName);
holder.cbCheck=(CheckBox)row.findViewById(R.id.checkBox);
row.setTag(holder);
}
else
{
holder=(PakistaniDrama)row.getTag();
}
holder.tvDramaName.setText(dramaList.get(position).getDramaName());
holder.cbCheck.setChecked(checks.get(position));
return row;
}
В вашей logcat вы заметите, что convertview является нулевым для всех видимых строк, потому что изначально в утилите не было представлений (то есть элементов), поэтому ваш getView() создает новое представление для каждого из видимых элементов, но как только вы прокрутите вверх и элемент 1 выйдет из экрана, он будет отправлен в Recycler с его текущим состоянием (например, TextView 'text' или в моем случае, если флажок установлен, он будет связан с представлением и хранится в утилизаторе).
Теперь, когда вы прокручиваете вверх/вниз, ваше представление списка не будет создавать новое представление, оно будет использовать представление, которое находится в вашем утилизаторе. В вашей Logcat вы заметите, что 'convertView' не является нулевым, потому что ваш новый элемент 8 будет нарисован с использованием convertview, то есть, в основном, он берет представление элемента 1 из переработчика и надувает элемент 8 вместо него, и вы можете наблюдать что в моем коде. Если у вас был флажок и если вы отметили его в позиции 0 (скажем, у элемента 1 был флажок, и вы его установили), поэтому при прокрутке вниз вы увидите, что флажок элемента 8 уже установлен, поэтому просмотр списка использует тот же вид, не создает для вас нового из-за оптимизации производительности.
Важные вещи
1 Никогда не устанавливайте layout_height
и layout_width
вашего списка в wrap_content
как getView()
заставит ваш адаптер получить некоторый дочерний getView()
для измерения высоты представлений, которые будут отображаться в виде списка, и может вызвать неожиданное поведение, например, возвращать convertview, даже если список не match_parent
использует match_parent
или фиксированную ширину/высоту.
2 Если вы хотите использовать какой-либо макет или представление после представления списка, вам могут layout_height
в голову вопросы, если я установлю layout_height
на fill_parent
представление после представления списка не будет отображаться при переходе вниз по экрану, поэтому лучше поместить свой просмотр списка внутри макета. Например, Linear Layout и установите высоту и ширину этого макета в соответствии с вашими требованиями и присвойте атрибуту height и width вашего просмотра списка свой макет (например, если ширина макета равна 320, а высота равна 280), тогда ваш список должен иметь одинаковую высоту и ширину. Это скажет getView() о точной высоте и ширине представлений, которые будут отображаться, и getView() не будет снова и снова вызывать некоторые случайные строки, и другие проблемы, такие как возвращение представления преобразования даже до того, как прокрутка не произойдет, у меня есть тест это само по себе, если мой просмотр списка не был внутри lineaLayout, у него также были проблемы, такие как повторение вызова представления и преобразование представления, так как помещение Listview внутри LinearLayout работало для меня как волшебство (не знаю почему)
01-01 14:49:36.606: I/System.out(13871): getview 0 null
01-01 14:49:36.636: I/System.out(13871): getview 0 [email protected]
01-01 14:49:36.636: I/System.out(13871): getview 1 and[email protected]
01-01 14:49:36.646: I/System.out(13871): getview 2 [email protected]
01-01 14:49:36.646: I/System.out(13871): getview 3 [email protected]
01-01 14:49:36.656: I/System.out(13871): getview 4 [email protected]
01-01 14:49:36.666: I/System.out(13871): getview 5 [email protected]
01-01 14:49:36.666: I/System.out(13871): getview 0 [email protected]
01-01 14:49:36.696: I/System.out(13871): getview 0 [email protected]
01-01 14:49:36.706: I/System.out(13871): getview 1 null
01-01 14:49:36.736: I/System.out(13871): getview 2 null
01-01 14:49:36.756: I/System.out(13871): getview 3 null
01-01 14:49:36.776: I/System.out(13871): getview 4 null
Но теперь это решено, я знаю, я не так хорош в объяснении, но, как я потратил весь день, чтобы понять, я думал, что другие новички, как я, могут получить помощь из моего опыта, и я надеюсь, что теперь вы, люди, будете иметь немного понимания структуры ListView, как это работает, поскольку это действительно грязно и хитро, поэтому новички нашли слишком много проблем с пониманием этого