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

edz*_*ion 159 java android listview

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

class ResultsListAdapter extends ArrayAdapter<RecordItem> {
Run Code Online (Sandbox Code Playgroud)

在重写的'getView'方法中,我做了一个打印来检查它是什么位置以及它是否是convertView:

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

此输出(当列表首次显示时,尚未输入用户)

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  
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

以及每一行的布局:

<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>
Run Code Online (Sandbox Code Playgroud)

感谢您的时间

Rom*_*Guy 268

这不是一个问题,绝对不能保证getView()将被调用的顺序也不能保证多少次.在你的特殊情况下,你ListView通过给它一个最糟糕的事情height=wrap_content.这迫使ListView在布局时测量适配器中的几个孩子,知道它应该有多大.这是提供ListViewconvertViews你看到传递给getView()您滚动甚至之前.

  • @cdpnet他确实说过它为什么这样做,你的`ListView`的高度为'wrap_content`,所以它不确定它的高度因此它会让一些孩子成为一种测试人员,看看它适合什么.你的`ListView`到`fill_parent`然后检查你的日志应该大大减少调用. (44认同)
  • 将ListView设置为layout_height = wrap_content时应该有一个警告,因为它会导致很多性能问题. (28认同)
  • 我觉得这不是一个好理由.如果你想能够改变,那很好,但目前它还没有回答为什么它会这样做? (10认同)
  • 2.3和4.x时代ListView之间的行为发生了重大变化.外卖是,正如ListView设计的那样,您的cells/list_items需要是纯视图,并且需要针对快速绘制进行优化.根据RoView提供的ListView上的Google I/O演讲,可能只调用getView来优化视图渲染并丢弃结果.虽然在我看来这不像iOS UITableView那样开发人员友好,但事实并非如此. (4认同)
  • 非常感谢!我不明白为什么经常调用getView().我将wrap_content转换为fill_parent,现在我的应用程序又快了:) (4认同)
  • 我的列表视图都设置为match_parent,但它仍然发生:( (4认同)

小智 53

尝试使用列表视图match_parentlayout_height属性.它会阻止getView()被频繁调用.

  • 请注意,对于API级别8及更高级别,`fill_parent`应替换为`match_parent`. (8认同)
  • 请注意,Fred T指定了LIST VIEW的layout_height ...而不是行,这是我一遍又一遍地尝试的 (4认同)

Eug*_*mak 45

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


有用的注意事项请注意您是否有嵌套项目.你必须将"最高"的一个改为match_parent.希望它可以帮助某人.


Sid*_*ant 7

我无法回答你的"为什么"的问题,但我肯定有一个解决刺激性的" ListView项目重复 "问题的问题(如果你的集合中的项目超过屏幕高度).

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

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

希望这有助于朋友!

最诚挚的问候,Siddhant