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

时间:2009-08-24 04:27:21

标签: android listview

我将数据从Cursor加载到listview,但我的Listview并没有真正显示“平滑”。当我在ListView中的scollbar上上下拖动时,数据会发生变化。有些项目看起来像我的列表中的重复显示。 我有一个“复杂的ListView”(两个textview,一个imageview)所以我用newView(),bindView()来显示数据。有人能帮助我吗?

5 个答案:

答案 0 :(得分:11)

我将向您介绍如何解决此类问题。可能这会对你有帮助。

因此,在列表适配器中,您有这样的代码:

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

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

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

holder.label.setText(getLabel());

所以它会像下面这样照顾:

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

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

可能会有所帮助。

答案 1 :(得分:8)

ListView是一个棘手的野兽。

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

如果您使用自定义视图,则希望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;
}

如果您没有使用自己的自定义视图,只需通过调用new MyCustomView()

替换对inflater.inflate(R.layout.my_layout,null)的通话

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

从他的谈话和我自己的经验中的重要性来看,

  • 使用convertView
  • 如果您有图像,请不要动态缩放图像。使用Bitmap.createScaledBitmap创建缩放位图并将其放入您的视图
  • 使用ViewHolder,这样您就不必每次都调用一堆findViewByIds()
  • 降低列表视图中视图的复杂性。子视图越少越好。相对于LinearLayout,RelativeLayout比这更好。如果您正在实施自定义视图,请务必使用。

答案 2 :(得分:1)

我也面临这个问题,但在我的情况下,我使用线程来获取外部图像。重要的是当前执行的线程在重用时不会更改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);
}

然后在提取线程中我正在进行重要检查

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();

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

答案 3 :(得分:1)

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

答案 4 :(得分:0)

如果您以错误的方式处理它,您可以看到多行中的重复文本。我最近在博客上写了一篇关于它的文章 - 请参阅here。除此之外,您可能需要查看ListView performance optimization。一般来说,这是因为视图重用,我已经看过很多次了。