BaseAdapter中的setImageBitmap #getView不会更新ImageView

时间:2013-01-27 00:22:10

标签: android android-2.1-eclair

我有一个应用程序可以在后台线程中下载一堆图像。在下载每个图标时,我将其添加到我的自定义适配器中的ArrayList中,该适配器是BaseAdapter的子类。 ListView中使用BaseAdapter的每一行都有一个ImageView。在getView中,我执行以下操作。

public View getView(int position, View convertView, ViewGroup parent) {
    final MyCustomImageClass imageObject = data.get(position);
    View vi = convertView;

    if(convertView==null) {
        vi = inflater.inflate(R.layout.list_row, null);
    }

    ImageView thumbnail = (ImageView)vi.findViewById(R.id.list_image);
    File appDir = new File(Utils.getAppFilesDir() +"");
    File imageFolder = new File(appDir, imageObject.getImageFolderName());
    File imageDir = new File(imageFolder, imageObject.getIconFilename());
    Log.e("myapp", "row image dir: " + imageDir.toString());
    if(imageDir.exists()) {
        Bitmap imageBitmap = BitmapFactory.decodeFile(imageDir.toString());
        thumbnail.setImageBitmap(imageBitmap);
    }
    thumbnail.invalidate();
}

但我所看到的是thumbnail正在重复使用旧图像。就像,前几行将具有相同的缩略图,即使我在logcat中看到它们的路径不同。

如何告诉ListView中的Image,它的ImageView有一个新的Bitmap图像?

2 个答案:

答案 0 :(得分:0)

ListView中的每一行都会被回收,因此当一个人离开屏幕时,下一个将继续使用该容器。您可能不满足新更新的if上的ImageView语句,因此图像未设置为您想要的,因此它只是重用旧的。确保您的imageDir.exists()成功完成,以确保新视图能够正确更新。另外,我认为没有任何理由要求无效。

编辑:我明白为什么你现在正在调用invalidate(),但它仍然没有必要。我建议使用ImageView的默认图像,就像android提供的一样,然后执行以下操作:

if(imageBitmap != null)
  thumbnail.setImageBitmap(imageBitmap);
else
  thumbnail.setImageDrawable(R.drawable.content_picture);

其中R.drawable.content_picture是默认的“无图片展示”图像,也是为XML文件中的ImageView定义的图像。

最后,您应该考虑使用ViewHolder来加速ListView的呈现。以下是一个示例:How to implement a view holder?

如果我在这里说的话没有意义,那就请求澄清。

答案 1 :(得分:0)

适配器正在回收整个列表项,而不仅仅是图像。在等待新位图被解码时,您需要将图像资源重置为占位符。

作为旁注,你真的不应该在UI线程上读取磁盘或解码位图。 getView()方法应该可以非常快速地返回,这就排除了在那里做任何实际工作。查看开发指南,了解有关如何处理位图的好提示:

http://developer.android.com/training/displaying-bitmaps/index.html