it-roy-ru.com

пользовательский метод getView адаптера списка, вызываемый несколько раз и не в последовательном порядке

У меня есть настраиваемый адаптер списка:

class ResultsListAdapter extends ArrayAdapter<RecordItem> {

в переопределенном методе getView я делаю печать, чтобы проверить, какая позиция и является ли она convertView или нет:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        System.out.println("getView " + position + " " + convertView);

Вывод этого (при первом отображении списка, пользовательский ввод пока отсутствует)

04-11 16:24:05.860: INFO/System.out(681): getView 0 null  
04-11 16:24:29.020: INFO/System.out(681): getView 1 [email protected]  
04-11 16:25:48.070: INFO/System.out(681): getView 2 [email protected]  
04-11 16:25:49.110: INFO/System.out(681): getView 3 [email protected]  
04-11 16:25:49.710: INFO/System.out(681): getView 0 [email protected]  
04-11 16:25:50.251: INFO/System.out(681): getView 1 null  
04-11 16:26:01.300: INFO/System.out(681): getView 2 null  
04-11 16:26:02.020: INFO/System.out(681): getView 3 null  
04-11 16:28:28.091: INFO/System.out(681): getView 0 null  
04-11 16:37:46.180: INFO/System.out(681): getView 1 [email protected]  
04-11 16:37:47.091: INFO/System.out(681): getView 2 [email protected]  
04-11 16:37:47.730: INFO/System.out(681): getView 3 [email protected]  

AFAIK, хотя я не смог найти это явно, getView () вызывается только для видимых строк. Поскольку мое приложение начинается с четырех видимых строк, по крайней мере, номера позиций, циклически изменяющиеся от 0 до 3, имеют смысл. Но в остальном беспорядок

  • Почему getview вызывается для каждого ряда три раза? 
  • Откуда приходят эти convertView, когда я еще не прокрутил?

Я сделал небольшой поиск и, не получив хорошего ответа, заметил, что люди связывают эту проблему с проблемами компоновки. Так что в случае, вот макет, который содержит список:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_height="fill_parent"
    Android:layout_width="fill_parent" 
    Android:orientation="vertical" >

    <TextView Android:id="@+id/pageDetails"
        Android:layout_width="fill_parent" 
        Android:layout_height="wrap_content" />

    <ListView Android:id="@+id/list"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content" 
        Android:drawSelectorOnTop="false" />

</LinearLayout>

и расположение каждого отдельного ряда:

<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="108dp"    
Android:padding="4dp">

<ImageView
    Android:id="@+id/thumb"        
    Android:layout_width="120dp"
    Android:layout_height="fill_parent"        
    Android:layout_alignParentTop="true"
    Android:layout_alignParentBottom="true"
    Android:layout_alignParentLeft="true"
    Android:layout_marginRight="8dp"        
    Android:src="@drawable/loading" />

<TextView  
    Android:id="@+id/price"
    Android:layout_width="wrap_content"
    Android:layout_height="18dp"         
    Android:layout_toRightOf="@id/thumb"
    Android:layout_alignParentBottom="true"       
    Android:singleLine="true" />

<TextView  
    Android:id="@+id/date"
    Android:layout_width="wrap_content"
    Android:layout_height="18dp"         
    Android:layout_alignParentBottom="true"
    Android:layout_alignParentRight="true" 
    Android:paddingRight="4dp"       
    Android:singleLine="true" />

<TextView
    Android:id="@+id/title"
    Android:layout_width="fill_parent"
    Android:layout_height="wrap_content"
    Android:textSize="17dp" 
    Android:layout_toRightOf="@id/thumb"
    Android:layout_alignParentRight="true"
    Android:layout_alignParentTop="true"
    Android:paddingRight="4dp"   
    Android:layout_alignWithParentIfMissing="true"
    Android:gravity="center" />

</RelativeLayout>

Спасибо за ваше время

154
edzillion

Это не проблема, нет абсолютно никакой гарантии ни в отношении порядка вызова функции getView(), ни во сколько раз. В вашем конкретном случае вы делаете худшее из возможных с ListView, передав ему height=wrap_content. Это вынуждает ListView измерять несколько дочерних элементов адаптера во время макета, чтобы знать, насколько большим он должен быть. Это то, что обеспечивает ListViewconvertViews, который вы видите переданным getView() даже до того, как вы прокрутите.

263
Romain Guy

Попробуйте с match_parent в свойстве layout_height представления списка. Это предотвратит частый вызов getView().

53
Fred T

Я избавился от этой проблемы, когда изменил layout_width и layout_height на match_parent (изменение только layout_height не помогло).


Полезная заметка будьте осторожны, если у вас есть вложенные элементы. Вы должны изменить самый высокий на match_parent . Надеюсь, это поможет кому-то.

45
Eugene Chumak

Я не могу ответить на ваш вопрос «Почему», но у меня определенно есть решение проблемы раздражающей проблемы «ListView items repeating» (если в вашей коллекции элементов больше высоты экрана).

Как уже упоминали многие люди, оставьте свойство Android: layout_height тега ListVew как fill_parent.

Что касается функции getView (), решение состоит в том, чтобы использовать статический класс с именем ViewHolder. Проверьте это пример. Он успешно выполняет задачу добавления всех элементов в массив Array или ArrayCollection.

Надеюсь, это поможет друзьям!

С наилучшими пожеланиями, Сиддхант

7
Siddhant

Вопросы: почему Adapter многократно вызывает getView ()? Ответ. Поскольку визуализация Listview при прокрутке обновляет представление с помощью следующих последующих представлений, для какой адаптер должен получать представления, вызывая getView ().

Вопросы: Почему он вызывает меньше, если для ширины и высоты списка установлено значение fill_parent? Ответ: Потому что, поскольку инфлятор имеет фиксированный размер для области экрана для списка, он рассчитывается один раз для рендеринг взглядов на экран.

Надеюсь, это разрешит ваш запрос.

4
jitain sharma

У меня была такая же проблема с выпадающим в AutoCompleteTextView. Я боролся с проблемой в течение двух дней, пока я не приехал сюда, и вы не показали мне решение.

Если я напишу dropDownHeight = "match_parent", проблема исправлена. Теперь проблема связана с пользовательским интерфейсом (когда у вас есть один элемент, раскрывающийся список слишком велик), но проблема множественных вызовов (гораздо более важная) устранена.

Спасибо!!

3
Pau Arlandis Martinez

У меня та же проблема. Если для меня установлено значение fill_parent, то я получаю «обычно» 2 вызова на строку. Но если я установлю высоту моего ListView на точное значение, скажем, 300dp, то я получу ровно один вызов GetView на строку. 

Таким образом, мне кажется, что единственный способ - это сначала определить высоту экрана, а затем программно установить высоту listvilew на это значение. Мне это не нравится Я надеюсь, что есть лучший способ.

2
bobetko

«Почему getview вызывается для каждой строки три раза?» Потому что getView вызывается, когда вы прокручиваете список, и лучше сказать, что он вызывается при изменении позиции представления вашего списка!

2
Ungureanu Liviu

Для всех вас, кто все еще (после установки heightListView в match_parent) застрял (как я был):

Вы также должны установить height родительского макета в match_parent.

Смотрите пример ниже. LinearLayout является родителем здесь:

<LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:orientation="vertical">

        <TextView
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:text="@string/something" />

        <ListView
            Android:id="@+id/friendsList"
            Android:layout_width="match_parent"
            Android:layout_height="match_parent" />
    </LinearLayout>
2
B001ᛦ

Это может быть поздно, но если вы используете layout_weight, не забывайте всегда устанавливать layout_width="0dp"

0
Kuti Gbolahan