快速滚动时以错误的位置调用 getView [英] getView called with wrong position when scrolling fast

查看:14
本文介绍了快速滚动时以错误的位置调用 getView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

相当新的 Android 开发者.

fairly new Android developer here.

我遇到了一个奇怪的问题,我不知道如何解决.我读过很多这里的问题,听起来它们与我遇到的问题相同,但他们问题的解决方案似乎从未适用于这里发生的事情.

I've come across a strange problem that I'm not sure how to work around. I've read a lot of problems around here that sound like they are the same problem I am having, but the solutions to their problems never seemed applicable to what is going on here.

我使用一个单独的类设置了一个自定义 listView,该类扩展了 BaseAdapter 并使用了一个视图持有者(我设置了这个,查看了自定义列表视图的各种不同示例).它有一个文本视图、一个按钮、一个进度条和一个图像按钮,这些项目根据用于下载文件的 AsyncTask 隐藏/更改.

I have a custom listView set up using a separate class that extends BaseAdapter and uses a view holder (I set this up looking at various different examples of custom listviews). It's got a text view, a button, a progress bar, and an image button, and these items are hidden/changed based on an AsyncTask used to download a file.

当我缓慢滚动列表时,一切正常.当我快速向上/向下滚动列表时,就好像列表中某些单元格的视图被重新分配给其他单元格.

Everything works fine when I scroll through the list slowly. When I scroll the list rapidly up/down, it is as if the views of some cells in the list get re-assigned to other cells.

我将此行放在适配器类中getView"方法的顶部:

I put this line into the top of my "getView" method in my adapter class:

    @Override
    public View getView(final int pos, View convertView, ViewGroup parent)
    {
        Log.i("ks3","getView called, position is " + pos);

我的列表中有 7 个项目,其中 6 个适合屏幕显示.当它第一次显示时,我在我的日志中看到:

I have 7 items in my list, and 6 of them fit on screen. When it first gets displayed, I see this in my log:

getView called, position is 0
getView called, position is 1
getView called, position is 2
getView called, position is 3
getView called, position is 4
getView called, position is 5

当我慢慢向下滚动到下一项时,接下来会打印出来:

When I scroll down slowly to the next item, this is printed out next:

getView called, position is 6

当我向上滚动时,这个:

When I scroll back up, this:

getView called, position is 0

慢慢地下降和上升可以完美地产生这些结果.

Going down and up slowly produce these results flawlessly.

当我开始快速来回滚动时,它会多次打印此消息,主要显示位置为 6 和 0,但偶尔我也会看到这些:

When I start scrolling back and forth quickly, it prints out this message a bunch of times, mostly showing 6 and 0 as the position, but occasionally I will see these as well:

getView called, position is 1
getView called, position is 5

位置 1 和 5 不应被调用,因为它们始终显示在屏幕上.就好像 getView 被搞得一团糟.同时,正如我之前所说,我的清单看起来很奇怪.图像按钮将向上或向下移动不应该出现的单元格.

Positions 1 and 5 should not be getting called, as they are always on-screen. It is as if getView got all jumbled up. At the same time, as I stated before, my list will look strange. Image buttons will be moved up or down a cell where they should not be.

如果我回到平滑滚动,我会再次看到位置的 0 和 6.

If I go back to scrolling smoothly, I see only 0's and 6's for position again.

老实说,我不确定如何解决这个问题.我想也许我可以限制您滚动列表的速度,但一直找不到任何有效的内容.

I honestly am not sure how to work around this. I thought maybe I could limit how fast you are able to scroll through the list, but haven't been able to find anything that works.

谢谢!

我想就这个问题更新一些内容.第一个是,从这里的评论和关于 listView 的谷歌视频,我注意到 getView 可以被调用用于其他事情,而不是我想象的它的用途,例如测量,所以我不应该感到震惊我最初认为是我的问题的一部分(我认为 getView 被错误的位置调用).

I wanted to update a couple things regarding this question. The first being that, from a comment here and from the Google video on listView, it has come to my attention that getView can be called for other things then what I imagined it was for, such as measurements, and so I should not be alarmed by what I originally thought was part of my problem (that being that I thought getView was being called with the wrong positions).

其次,我多次看到在适配器内缓存视图"是一个非常糟糕的主意.我不太清楚这是什么意思,但我很确定这是我做错的事情之一(我保存了一个按钮的实例、progressBar、imageButton...).

Secondly, I saw multiple times that it is a very bad idea to "cache views inside your adapter." I am not exactly clear on what this means, but I'm pretty sure it is one of the things I am doing wrong (I save an instance of a button, progressBar, imageButton...).

那个,以及我在 getView 之外更新视图并且我不使用 notifyDataSetChanged() 的事实;这些在一起可能会导致一些奇怪的事情发生.

That, along with the fact that I update the views outside of getView and I don't use notifyDataSetChanged(); those together are probably causing some wonky stuff to happen.

推荐答案

ListView 在屏幕上的不同位置重用视图是正确的.这是一种优化,通过不一直分配新视图来保持合理和快速的内存使用.

You are correct that ListView is reusing views in different places on the screen. It's an optimization to keep memory use reasonable and speedy by not allocating new views all the time.

您可能错误地使用了 LiewView.观看 关于如何正确使用 ListView 以获得整个故事,但这里是亮点:

Chances are that you're using LiewView incorrectly. Watch this talk on how to properly use ListView to get the whole story, but here's the highlights:

  1. 位置"是指您的数据在适配器列表中的位置.如果您的适配器数据在一个数组中,这将是该数组的索引.
  2. ID"指的是数据本身的值.如果你有一个名字列表并使用它们,他们的位置会改变,但他们的 ID 不会.
  3. 索引"是指视图相对于可查看屏幕区域的相对位置.您可能永远不需要这个.
  4. 不要在适配器的 getView() 方法之外操作视图(或尝试缓存它们),否则会出现奇怪的行为.
  5. 如果对 getView(int, View, ViewGroup) 的调用提供了一个视图实例,则填充其字段而不是填充全新的视图.假设您已正确实现 getItemType(),您将始终获得正确的 View 类型以重新填充.
  6. 尽可能快地制作您的 getView() 方法,并且只在其他线程上执行繁重的工作.
  7. 仅仅因为名为 getView() 的容器并不一定意味着会显示数据.该框架将这些用于测量目的.由于工作可能会被丢弃,这是确保 getView() 尽可能快的另一个原因.
  8. 当您需要在屏幕上显示的数据发生问题时,请说您的下载已完成,这时您将调用 notifyDataSetChanged().不要直接摆弄视图,当它被重绘时,它们将在下一个 UI 循环中填充.
  1. "Position" refers to the location of your data in the adapter list. If your adapter data is in an array, this would be the index into that array.
  2. "ID" refers to the value of the data itself. If you have a list of names and resort them, their position will change, but their ID will not.
  3. "Index" refers to the relative location of a view with respect to the viewable screen area. You'll probably never need this.
  4. Do not manipulate views (or attempt to cache them) outside of your adapter's getView() method or you will get strange behavior.
  5. If the call to getView(int, View, ViewGroup) provides a view instance, populate its fields instead of inflating totally new views. Assuming you've correctly implemented getItemType(), you'll always get the right View type to repopulate.
  6. Make your getView() method as fast as you possibly can, and only do heavy lifting on other threads.
  7. Just because the container called getView() doesn't necessarily mean the data will be displayed. The framework uses these for measurement purposes. Since the work could be thrown away, this is another reason to make sure that getView() is as fast as you can make it.
  8. When something happens to your data which you need to show on screen, say your download is complete, that's when you call notifyDataSetChanged(). Don't fiddle with the views directly, they'll be populated on the next UI loop when it gets redrawn.

刚刚花了几天时间重新编写了一个天真的实现的 ListView,我感受到了你的痛苦.不过,结果是值得的!

Having just spent a few days reworking a ListView that was implemented naively, I feel your pain. The results have been worth it, though!

这篇关于快速滚动时以错误的位置调用 getView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆