如何在android中“顺利”加载Listview

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1320478/
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-20 02:55:52  来源:igfitidea点击:

How to load the Listview "smoothly" in android

androidlistview

提问by Dennie

I load data from Cursor to listview, but my Listview not really display "smooth". The data change when I drag up and down on the scollbar in my ListView. And some items look like duplicate display in my list. I hava a "complex ListView" (two textview, one imageview) So I used newView(), bindView() to display data. Can someone help me?

我将数据从光标加载到列表视图,但我的列表视图并未真正显示“平滑”。当我在 ListView 中的 scollbar 上上下拖动时,数据会发生变化。有些项目在我的列表中看起来像是重复显示。我有一个“复杂的 ListView”(两个文本视图,一个图像视图)所以我使用 newView()、bindView() 来显示数据。有人能帮我吗?

采纳答案by Lyubomyr Dutko

I will describe you how to get such issue that you have. Possibly this will help you.

我将向您描述如何解决您遇到的此类问题。也许这会对你有所帮助。

So, in list adapter you have such code:

所以,在列表适配器中你有这样的代码:

public View getView(int position, View contentView, ViewGroup arg2)
    {
        ViewHolder holder;

        if (contentView == null) {
            holder = new ViewHolder();
            contentView = inflater.inflate(R.layout.my_magic_list,null);
            holder.label = (TextView) contentView.findViewById(R.id.label);
            contentView.setTag(holder);
        } else {
            holder = (ViewHolder) contentView.getTag();
        }

        holder.label.setText(getLabel());

        return contentView;
    }

As you can see, we set list item value only after we have retrieved holder.

如您所见,我们仅在检索到持有者后才设置列表项值。

But if you move code into above if statement:

但是如果你将代码移到上面的 if 语句中:

holder.label.setText(getLabel());

so it will look after like below:

所以它会像下面这样处理:

if (contentView == null) {
   holder = new ViewHolder();
   contentView = inflater.inflate(R.layout.my_magic_list,null);
   holder.label = (TextView) contentView.findViewById(R.id.label);
   holder.label.setText(getLabel());
   contentView.setTag(holder);
}

you will have your current application behavior with list item duplication.

您将拥有与列表项重复的当前应用程序行为。

Possibly it will help.

也许它会有所帮助。

回答by emmby

ListView is a tricky beast.

ListView 是一个棘手的野兽。

Your second question first: you're seeing duplicates because ListView re-uses Views via convertView, but you're not making sure to reset all aspects of the converted view. Make sure that the code path for convertView!=nullproperly sets all of the data for the view, and everything should work properly.

您的第二个问题首先:您看到重复项,因为 ListView 通过 convertView 重新使用视图,但您没有确保重置转换后的视图的所有方面。确保convertView!=null正确设置视图的所有数据的代码路径,并且一切都应该正常工作。

You'll want your getView()method to look roughly like the following if you're using custom views:

getView()如果您使用自定义视图,您将希望您的方法大致如下所示:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final MyCustomView v = convertView!=null ? (MyCustomView)convertView : new MyCustomView();
    v.setMyData( listAdapter.get(position) );
    return v;
}

If you're not using your own custom view, just replace the call to new MyCustomView()with a call to inflater.inflate(R.layout.my_layout,null)

如果你不使用你自己的自定义视图,只需更换呼叫new MyCustomView()通过调用inflater.inflate(R.layout.my_layout,null)

As to your first question, you'll want to watch Romain's techtalk on ListView performance here: http://code.google.com/events/io/sessions/TurboChargeUiAndroidFast.html

至于你的第一个问题,你会想在这里观看 Romain 关于 ListView 性能的技术演讲:http: //code.google.com/events/io/sessions/TurboChargeUiAndroidFast.html

From his talk and in order of importance from my own experience,

从他的谈话和我自己的经验中按重要性排序,

  • Use convertView
  • If you have images, don't scale your images on the fly. Use Bitmap.createScaledBitmap to create a scaled bitmap and put that into your views
  • Use a ViewHolder so you don't have to call a bunch of findViewByIds() every time
  • Decrease the complexity of the views in your listview. The fewer subviews, the better. RelativeLayout is much better at this than, say, LinearLayout. And make sure to use if you're implementing custom views.
  • 使用转换视图
  • 如果您有图像,请不要即时缩放图像。使用 Bitmap.createScaledBitmap 创建缩放位图并将其放入您的视图中
  • 使用 ViewHolder 这样你就不必每次都调用一堆 findViewByIds()
  • 降低列表视图中视图的复杂性。子视图越少越好。在这方面,RelativeLayout 比 LinearLayout 好得多。如果您要实现自定义视图,请确保使用。

回答by Karussell

I'm facing this problem as well, but in my case I used threads to fetch the external images. It is important that the current executing thread do not change the imageView if it is reused!

我也面临这个问题,但就我而言,我使用线程来获取外部图像。重要的是当前正在执行的线程如果被重用,不要改变 imageView!

public View getView(int position, View vi, ViewGroup parent) {
ViewHolder holder;
String imageUrl = ...;

if (vi == null) {
    vi = inflater.inflate(R.layout.tweet, null);
    holder = new ViewHolder();
    holder.image = (ImageView) vi.findViewById(R.id.row_img);
    ...
    vi.setTag(holder);
} else {
    holder = (ViewHolder) vi.getTag();      
}
holder.image.setTag(imageUrl);
...
DRAW_MANAGER.fetchDrawableOnThread(imageUrl, holder.image);
}

And then on the fetching thread I'm doing the important check:

然后在获取线程上我正在做重要检查

final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
     // VERY IMPORTANT CHECK
    if (urlString.equals(url))
        imageView.setImageDrawable((Drawable) message.obj);
};

Thread thread = new Thread() {  

@Override
public void run() {
    Drawable drawable = fetchDrawable(urlString);
    if (drawable != null) {
        Message message = handler.obtainMessage(1, drawable);
        handler.sendMessage(message);
    }
}};
thread.start();

One could also cancel the current thread if their view is reused (like it is described here), but I decided against this because I want to fill my cache for later reuse.

如果他们的视图被重用(就像这里描述的那样),也可以取消当前线程,但我决定不这样做,因为我想填充我的缓存以供以后重用。

回答by insomniac

Just one tip: NEVER use transparent background of item layout - it slows performance greatly

只是一个提示:永远不要使用项目布局的透明背景 - 它会大大降低性能

回答by MariuszP

You can see the reocurring text in multiple rows if you handle it in the wrong way. I've blogged a bit about it recently - see here. Other than that you might want to take a look at ListView performance optimization. Generally it's because of the view reuse and I've seen it few times already.

如果您以错误的方式处理它,您可以在多行中看到重复出现的文本。我最近写了一些关于它的博客 - 请参阅此处。除此之外,您可能想看看ListView performance optimization。通常是因为视图重用,我已经看过几次了。