自定义listview适配器getView方法被多次调用,并且没有连贯的顺序

时间:2010-04-11 18:55:45

标签: java android listview

我有一个自定义列表适配器:

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 个答案:

答案 0 :(得分:264)

这不是问题,绝对不能保证调用getView()的顺序也不能保证多少次。在您的特定情况下,您通过ListViewheight=wrap_content做最糟糕的事情ListView。这迫使ListView在布局时测量适配器中的几个孩子,以了解它应该有多大。这就是convertViews在您滚动之前向getView()提供{{1}}的内容。

答案 1 :(得分:53)

尝试使用列表视图的match_parent属性上的layout_height。它会阻止getView()经常被调用。

答案 2 :(得分:45)

当我将layout_width和layout_height都更改为 match_parent (仅更改layout_height没有帮助)时,我摆脱了这个问题。


有用的提示注意您是否有嵌套项目。您必须将“最高”的一个更改为 match_parent 。希望它可以帮到某人。

答案 3 :(得分:7)

我无法回答你的“为什么”的问题,但我肯定能解决令人恼火的“ ListView项目重复”问题的问题(如果你的收藏中的项目更多比屏幕高度。)

正如上面提到的许多人所提到的,将 ListVew 标记的 android:layout_height 属性保留为 fill_parent

关于getView()函数,解决方案是使用名为 ViewHolder 静态类。查看this示例。它成功地完成了在ur Array或ArrayCollection中添加所有项目的任务。

希望这有助于朋友们!

最诚挚的问候, Siddhant

答案 4 :(得分:4)

问:为什么Adapter多次调用getView()? Ans:当Listview渲染时,滚动会刷新它的视图以及下一个即将发生的视图      哪个适配器需要通过调用getView()来获取视图。

问题:如果listview的宽度和高度设置为fill_parent,为什么它的调用较少? Ans:因为充气器具有固定大小的屏幕区域列表,它计算一次      将视图渲染到屏幕上。

希望它能解决您的疑问。

答案 5 :(得分:4)

我在AutoCompleteTextView的下拉列表中遇到了同样的问题。我和这个问题争了两天,直到我到达这里,你告诉我解决方案。

如果我写dropDownHeight =&#34; match_parent&#34;问题是固定的。现在问题与UI有关(当你有一个项目时,下拉列表太大)但是多个调用的问题(更重要的)是固定的。

谢谢!

答案 6 :(得分:2)

“为什么getview要求每行三次?”  因为当您在列表视图上滚动时调用getView并且说得更好,然后在列表视图的位置发生更改时调用它!

答案 7 :(得分:2)

答案 8 :(得分:2)

对于所有仍然(将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> 是此处的父级:

$value = $_POST['value'];

答案 9 :(得分:0)

这可能要晚了,但是如果您使用的是layout_weight,请记住始终设置layout_width="0dp"

答案 10 :(得分:0)

我提出了这个解决方案,也许不是最好的解决方案,但是确实可以解决问题...

//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;
}

希望有帮助!