Java 自定义listview适配器getView方法被多次调用,且顺序不一致

Java 自定义listview适配器getView方法被多次调用,且顺序不一致,java,android,listview,Java,Android,Listview,我有一个自定义列表适配器: class ResultsListAdapter extends ArrayAdapter<RecordItem> { 该列表的输出(当列表首次显示时,还没有用户输入) 好的,虽然我找不到明确的声明,但是getView()只对可见行调用。由于我的应用程序以四行可见开始,至少位置编号从0-3循环是有意义的。但其余的都是一团糟: 为什么每行调用getview三次 当我还没有滚动时,这些视图来自哪里 我做了一些研究,没有得到一个好的答案,我注意到人们把这个

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

class ResultsListAdapter extends ArrayAdapter<RecordItem> {
该列表的输出(当列表首次显示时,还没有用户输入)

好的,虽然我找不到明确的声明,但是getView()只对可见行调用。由于我的应用程序以四行可见开始,至少位置编号从0-3循环是有意义的。但其余的都是一团糟:

  • 为什么每行调用getview三次
  • 当我还没有滚动时,这些视图来自哪里
我做了一些研究,没有得到一个好的答案,我注意到人们把这个问题和布局问题联系起来。在这种情况下,下面是包含列表的布局:

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

感谢您抽出时间

“为什么每行调用getview三次?”
因为当您在listview上滚动时会调用getView,更好地说,当列表视图的位置更改时会调用getView

这不是问题,绝对不能保证调用
getView()
的顺序和次数。在您的特定情况下,您正在使用
列表视图做最糟糕的事情,给它一个
height=wrap\u content
。这迫使
ListView
在布局时测量适配器中的几个子项,以了解它应该有多大。这就是为列表视图提供
convertViews
的功能,您可以在滚动之前看到它传递给
getView()

在列表视图的
layout\u height
属性上尝试
match\u parent
。它将防止频繁调用
getView()

我也有同样的问题。如果我将“高度”设置为“填充父对象”,则每行“通常”有2个呼叫。但,若我将ListView的高度设置为精确的值,比如说300dp,那个么每行正好得到一个GetView调用


所以,在我看来,唯一的方法是首先确定屏幕的高度,然后通过编程将listvilew的高度设置为该值。我不喜欢它。我希望有更好的方法。

我无法回答您的“为什么”问题,但我肯定有一个解决方案,可以解决恼人的“列表视图项目重复出现的问题(如果您的收藏中有超过屏幕高度的项目)

如上所述,将ListVew标记的android:layou height属性保留为fill\u parent

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

希望这能帮助朋友

致以最良好的祝愿,
Siddhant

当我将布局宽度和布局高度都更改为“匹配父项”(仅更改布局高度没有帮助)时,我就解决了这个问题



帮助说明如果有嵌套项,请小心。您必须将“最高”一个更改为匹配\u parent。希望它能帮助别人。

问题:为什么适配器多次调用getView()? Ans:当滚动时Listview呈现时,它会用下一个即将出现的视图刷新它的视图,例如 哪个适配器需要通过调用getView()来获取视图

问题:如果listview的宽度和高度设置为填充父对象,为什么调用更少? 答:因为充气机对列表的屏幕区域有固定的大小,所以它只计算一次 将视图渲染到屏幕上


希望它能解决您的问题。

我在AutoCompleteTextView中的下拉列表也遇到了同样的问题。我和这个问题斗争了两天,直到我来到这里,你给我看解决方案

如果我写dropdownhight=“match\u parent”,问题就解决了。现在,问题与UI有关(当您有一个项目时,下拉列表太大),但多个调用(更重要)的问题已经解决

谢谢

对于所有仍然(在将
列表视图的
高度设置为
匹配父项后)被卡住的人(就像我一样):

您还必须将父布局的
高度设置为
match\u 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>


这可能会很晚,但如果您使用的是
布局重量
请记住始终设置
布局宽度=“0dp”
我提出了这个解决方案,可能不是最好的解决方案,但是否有效

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

希望有帮助

好的,但是视图没有改变。当活动开始时,屏幕上有四行视图,在没有滚动或任何用户输入的情况下,每行有三个getView调用…这个答案是错误的。正确的答案是使用**包装内容**会导致大量调用getView。谢谢。有趣的是,这个问题已经休眠了好几个月,但在过去的几周里却出现了一些评论。我不再做这个项目,但因为我有一些时间,我会尝试一下,然后回到这里确认。再次感谢。这里也是,我每排接两个电话。行0,1,2,3,然后100毫秒后再行0,1,2,3-这在收集关于所看到行的统计数据时是一件痛苦的事情。我不认为这是一个很好的理由。如果你想改变,那没关系,但目前它没有回答为什么会这样做?@cdpnet他说了为什么会这样做,你的
ListView
的高度是
wrap\u content
,所以它不确定它的高度,因此它将一些孩子作为一种测试者,来看看适合什么。将您的
ListView
更改为
fill\u parent
,然后检查您的日志呼叫应该是戏剧性的
//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;
}