我将数据从Cursor加载到listview,但我的Listview并没有真正显示“平滑”。当我在ListView中的scollbar上上下拖动时,数据会发生变化。有些项目看起来像我的列表中的重复显示。 我有一个“复杂的ListView”(两个textview,一个imageview)所以我用newView(),bindView()来显示数据。有人能帮助我吗?
答案 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
从他的谈话和我自己的经验中的重要性来看,
答案 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。一般来说,这是因为视图重用,我已经看过很多次了。