Java 自定义列表视图适配器 getView 方法被多次调用,并且顺序不一致

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2618272/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:57:15  来源:igfitidea点击:

custom listview adapter getView method being called multiple times, and in no coherent order

javaandroidlistview

提问by edzillion

I have a custom list adapter:

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

class ResultsListAdapter extends ArrayAdapter<RecordItem> {

in the overridden 'getView' method I do a print to check what position is and whether it is a convertView or not:

在重写的“getView”方法中,我打印以检查位置是什么以及它是否是 convertView:

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

The output of this (when the list is first displayed, no user input as yet)

这个的输出(当列表第一次显示时,还没有用户输入)

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, though I couldn't find it stated explicitly, getView() is only called for visible rows. Since my app starts with four visible rows at least the position numbers cycling from 0-3 makes sense. But the rest is a mess:

AFAIK,虽然我找不到它明确说明, getView() 只调用可见行。由于我的应用程序从四个可见行开始,至少位置编号从 0-3 循环是有意义的。但剩下的就一团糟:

  • Why is getview called for each row three times?
  • Where are these convertViews coming from when I haven't scrolled yet?
  • 为什么对每一行调用 getview 三次?
  • 当我还没有滚动时,这些 convertViews 来自哪里?

I did a bit of reseach, and without getting a good answer, I did notice that people were associating this issue with layout issues. So in case, here's the layout that contains the list:

我做了一些研究,但没有得到一个好的答案,我确实注意到人们将这个问题与布局问题联系起来。因此,以防万一,这是包含列表的布局:

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

and the layout of each individual row:

以及每一行的布局:

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

Thank you for your time

感谢您的时间

采纳答案by Romain Guy

This is not an issue, there is absolutely no guarantee on the order in which getView()will be called nor how many times. In your particular case you are doing the worst thing possible with a ListViewby giving it a height=wrap_content. This forces ListViewto measure a few children out of the adapter at layout time, to know how big it should be. This is what provides ListViewwith the convertViewsyou see passed to getView()even before you scroll.

这不是问题,绝对不能保证getView()调用的顺序和次数。在您的特定情况下,您正在ListView通过给 a做最糟糕的事情height=wrap_content。这迫使ListView在布局时测量适配器外的几个孩子,以了解它应该有多大。这是提供ListViewconvertViews你看到传递给getView()您滚动甚至之前。

回答by Ungureanu Liviu

"Why is getview called for each row three times?" Because getView is called when you scroll on listview and to say better then that it is called when the position of an view of your list is changed!

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

回答by Fred T

Try with match_parenton the layout_heightproperty of the list view. It will prevent getView()to be called so often.

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

回答by bobetko

I am having the same issue. If I have height set to fill_parent, then I get "usually" 2 calls per row. But, if I set height of my ListView to exact value, let's say to 300dp, then I get exactly one GetView call per row.

我有相同的问题。如果我将 height 设置为 fill_parent,那么每行“通常”会收到 2 个调用。但是,如果我将 ListView 的高度设置为精确值,假设为 300dp,那么每行我都会得到一个 GetView 调用。

So, it seems to me that the only way is to first determine height of the screen, then programmatically set height of listvilew to that value. I don't like it. I hope there is a better way.

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

回答by Siddhant

I am not able to answer your "Why" question but i definitely have a solution to the problem of the irritating "ListView items repeating" problem(if you have items in ur collection which are more than the screen height).

我无法回答您的“为什么”问题,但我绝对有解决恼人的“ ListView 项目重复”问题的解决方案(如果您的收藏中的项目超过屏幕高度)。

As many people above have mentioned, keep the android:layout_heightproperty of the ListVewtag as fill_parent.

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

And about the getView() function, the solution is to use a static classcalled ViewHolder. Check out thisexample. It successfully does the task of adding all the items in ur Array or ArrayCollection.

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

Hope this helps friends!!

希望能帮到朋友!!

Best Regards, Siddhant

最好的问候, Siddhant

回答by Eugene Chumak

I got rid of this issue when I changed both layout_width and layout_height to match_parent(changing only layout_height didn't help).

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



Helpful notewatch out if you have nested items. You've got to change the "highest" one to match_parent. Hope it helps someone.

有用的注意事项如果您有嵌套的项目,请注意。您必须将“最高”更改为match_parent。希望它可以帮助某人。

回答by jitain sharma

Ques: Why Adapter calls getView() manytimes? Ans: As Listview renders on scrolling is refreshes it's view with next upcoming views, for which adapter needs to get views by calling getView().

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

Ques: Why it's calls lesser if listview width and height set to fill_parent? Ans: Because as inflator has the fixed size for the screen area for list it calculates once for rendering the views onto the screen.

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

Hope it will resolve your query.

希望它能解决您的疑问。

回答by Pau Arlandis Martinez

I was having the same problem with the dropdown in an AutoCompleteTextView. I was fighting with the problem for two days until I arrive here and you show me the solution.

我在 AutoCompleteTextView 的下拉菜单中遇到了同样的问题。我与这个问题斗争了两天,直到我到达这里并且您向我展示了解决方案。

If I write dropDownHeight="match_parent" the problem is fixed. Now the problem is related to UI (when you have one item the dropdown is too large) but the problem of multiple calls (much more important) is fixed.

如果我写 dropDownHeight="match_parent" 问题就解决了。现在问题与 UI 相关(当您有一个项目时,下拉列表太大)但多次调用的问题(更重要)已修复。

Thank you!!

谢谢!!

回答by B001?

For all of you who still (After setting the heightof the ListViewto match_parent) are stuck (like I was):

对于大家谁还是(设置后heightListViewmatch_parent)被卡住了(像我):

You also have to set the heightof the parent layout to match_parent.

您还必须height将父布局的 设置为match_parent

See example below. The LinearLayoutis the parent here:

请参阅下面的示例。这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>

回答by Kuti Gbolahan

This maybe coming late but if you are using layout_weightremember to always set layout_width="0dp"

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