пользовательский метод getView адаптера списка, вызываемый несколько раз и не в последовательном порядке - PullRequest
157 голосов
/ 11 апреля 2010

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

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 android.widget.RelativeLayout@43d415d8  
04-11 16:25:48.070: INFO/System.out(681): getView 2 android.widget.RelativeLayout@43d415d8  
04-11 16:25:49.110: INFO/System.out(681): getView 3 android.widget.RelativeLayout@43d415d8  
04-11 16:25:49.710: INFO/System.out(681): getView 0 android.widget.RelativeLayout@43d415d8  
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 android.widget.RelativeLayout@43cff8f0  
04-11 16:37:47.091: INFO/System.out(681): getView 2 android.widget.RelativeLayout@43cff8f0  
04-11 16:37:47.730: INFO/System.out(681): getView 3 android.widget.RelativeLayout@43cff8f0  

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

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

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

<?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>

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

Ответы [ 11 ]

265 голосов
/ 14 апреля 2010

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

53 голосов
/ 04 января 2011

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

45 голосов
/ 28 февраля 2012

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


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

7 голосов
/ 08 февраля 2012

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

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

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

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

С наилучшими пожеланиями, Siddhant

4 голосов
/ 24 июня 2015

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

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

Спасибо !!

4 голосов
/ 28 августа 2013

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

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

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

2 голосов
/ 28 июля 2016

Для всех вас, кто все еще (после установки height из ListView в 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 голосов
/ 06 января 2011

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

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

2 голосов
/ 12 апреля 2010

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

0 голосов
/ 02 июля 2019

Я сделал это решение, может быть, не самое лучшее, но работает ...

//initialize control string
private String control_input = " ";

тогда =

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View gridview = convertView;

    // change input_array for the array you use
    if (!control_input.equals(input_array[position])) {
        control_input = input_array[position];

        //do your magic

    } 

    return gridview;
}

надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...