我在android中遇到了listview的问题。当我开始向下滚动列表时,它非常慢,我看到GC被调用。当我在列表的底部时,一切都很顺利。我认为,此时我的ViewHolder可以完成这项工作。
但我无法找到调用GC的来源。我搜索了哪些导致:
DDMS 436816 byte[] 1 android.graphics.Bitmap nativeCreate
我不能解释那条线。我的ArrayAdapter
及其getView
方法如下所示:
public class DiagnoseAdapter extends ArrayAdapter<Visualizer> {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int type = TYPE_DEFAULT;
final Visualizer item = getItem(position);
switch(item.getType()){
case TYPE_DEFAULT:
convertView = DefaultTextView.getView(position, convertView, mlayoutInflater, item, parent);
break;
// more cases/types
}
return convertView;
}
}
正在调用类getView
DefaultTextView
方法
public class DefaultTextView{
public static View getView(int position, View convertView, LayoutInflater layoutInflater, Visualizer item, ViewGroup parent){
ViewHolder holder;
if (convertView == null || item.getReleatedObject() == null || convertView.getTag()!=TAG_DEFAULT) {
convertView = layoutInflater.inflate(R.layout.diagnose_item, null);
holder = new ViewHolder();
holder.value = (TextView) convertView.findViewById(R.id.diagnose_function_value);
holder.name = (TextView) convertView.findViewById(R.id.diagnose_function_setname);
holder.mLinLayout = (LinearLayout) convertView.findViewById(R.id.default_linlayout);
convertView.setTag(TAG_DEFAULT);
convertView.setTag(R.layout.diagnose_item,holder);
item.setReleatedObject(convertView);
} else {
holder = (ViewHolder) convertView.getTag(R.layout.diagnose_item);
}
holder.value.setText(item.toString());
holder.name.setText(item.getToolTip());
holder.mLinLayout.removeAllViews();
if (item.getUpdateFlag(4)) {
if (holder.back == null){
holder.back = new ImageView(convertView.getContext());
holder.back.setScaleType(ScaleType.FIT_CENTER);
holder.back.setAdjustViewBounds(true);
holder.back.setImageBitmap(bm1);
}
holder.mLinLayout.addView(holder.back);
}
if (item.getUpdateFlag(1)) {
if (holder.update == null){
holder.update = new ImageView(convertView.getContext());
holder.update.setScaleType(ScaleType.FIT_CENTER);
holder.update.setAdjustViewBounds(true);
holder.update.setImageBitmap(bm2);
}
holder.mLinLayout.addView(holder.update);
}
if (item.getUpdateFlag(2)) {
if (holder.timer == null){
holder.timer = new ImageView(convertView.getContext());
holder.timer.setScaleType(ScaleType.FIT_CENTER);
holder.timer.setAdjustViewBounds(true);
holder.timer.setImageBitmap(bm3)
}
holder.mLinLayout.addView(holder.timer);
}
if (item.getUpdateFlag(3)) {
if (holder.log == null){
holder.log = new ImageView(convertView.getContext());
holder.log.setScaleType(ScaleType.FIT_CENTER);
holder.log.setAdjustViewBounds(true);
holder.log.setImageBitmap(bm4);
}
holder.mLinLayout.addView(holder.log);
}
if (item.getUpdateFlag(0)) {
if (holder.forward == null){
holder.forward = new ImageView(convertView.getContext());
holder.forward.setScaleType(ScaleType.FIT_CENTER);
holder.forward.setAdjustViewBounds(true);
holder.forward.setImageBitmap(bm5);
}
holder.mLinLayout.addView(holder.forward);
}
return convertView;
}
static class ViewHolder {
TextView name, value;
ImageView back, update, timer, log, forward;
LinearLayout mLinLayout;
}
}
即使我对LinearLayout
发表评论,我也只有一个包含两个TextViews
的列表。
所以我的问题。我什么都错过了。有些蠢事吗?如何让ListView更流畅?
顺便说一句:我在另一个帖子中读到,如果ListView
具有属性android:cacheColorHint="#00000000
,则会发生这种情况。我没有这个属性。
我希望有人有解决方案。谢谢!
答案 0 :(得分:0)
关于GC来电的来源。如果我正确理解您的代码,每次回收ListView项目并调用removeAllViews()
时,都会删除先前动态创建的ImageView
,并对其Bitmap
进行垃圾回收。因此,如果您在xml布局中使用相同的ImageView
声明它,并根据您的Bitmap
替换getUpdateFlag()
,也许可以避免那些GC调用。
关于ListViews和Images的另外两件事。首先,如果图像太大,无论如何,ListView都会变得迟钝。如果是这种情况,您需要缩小图像(Loading Large Bitmaps Efficiently)。第二,也许你还需要实现一个Lazy List,它按需加载图像,有一个着名的问题 - &gt; How do I do a lazy load of images in ListView?
答案 1 :(得分:0)
我终于解决了我的问题。像上面一样,我认为问题是基于我的列表项的图像。但那不是问题。我没有正确使用我的ViewHolders
和getItemViewType(int position)
方法。我有一个包含许多不同项目布局的列表,我看到,我上面的代码为每个项目创建了一个新的convertView和一个新的ViewHolder,这不应该是。我找到了一个关于如何使用多项布局的精彩教程(参见下面的链接):