带有Glide的Android列表视图 - 加载后加倍的位图

时间:2016-01-30 21:27:58

标签: android listview android-glide

我正在开发一个Android应用程序。我的一个片段包含一个显示好友列表的简单列表视图。每个朋友都可以拥有自己的个人资料图片 - 由Glide图书馆设置。当用户没有设置配置文件时,将显示默认图像。我的问题是,每次,列表中的第一个元素获得相同的图片,该图片在列表的最后一个元素上设置,而不是默认图片。我的意思如图所示:

here

名为 wiktor 的用户设置了个人资料图片,当您看到第一个位置 bonzo 有wiktor的个人资料照片(bonzo应该有默认照片)

删除用户表单列表时也存在问题:

doubled profile pic

如你所见,我从朋友列表中删除了 majka ,然后下一个元素获取了她的照片。

默认配置文件图片在drawables的内部行布局xml中设置。

以下是我的listview适配器的代码:

public class FriendsAdapter extends ArrayAdapter<FriendData> {

static class FriendHolder {

    TextView friendName;
    TextView friendRank;
    ImageView friendIcon;
    ImageButton deleteFriendBtn;
    ImageButton banFriendBtn;
}

private List<FriendData> list;

public FriendsAdapter(Context context, int resource, List<FriendData> objects) {

    super(context, resource, objects);
    list = objects;
}

@Override
public View getView(final int position, View convertView, final ViewGroup parent) {

    final FriendData element = getItem(position);
    final FriendHolder viewHolder;
    if (convertView == null) {

        viewHolder = new FriendHolder();
        LayoutInflater inflater = LayoutInflater.from(getContext());
        convertView = inflater.inflate(R.layout.friend_layout, parent, false);
        viewHolder.friendIcon = (ImageView) convertView.findViewById(R.id.friendIcon);
        viewHolder.friendName = (TextView) convertView.findViewById(R.id.friendName);
        viewHolder.friendRank = (TextView) convertView.findViewById(R.id.friendRank);
        viewHolder.deleteFriendBtn = (ImageButton) convertView.findViewById(R.id.deleteFriendBtn);
        viewHolder.banFriendBtn = (ImageButton) convertView.findViewById(R.id.banFriendBtn);
        convertView.setTag(viewHolder);
    } else {
        viewHolder = (FriendHolder) convertView.getTag();
    }

    if (element.getPhoto() != null) {

        String photo = S3ImageHandler.SMALL_PROFILE_ICON_PREFIX + element.getPhoto();
        String url = String.format(S3ImageHandler.AMAZON_PROFILE_DOWNLOAD_LINK, photo);
        Glide.with(getContext())
                .load(url)
                .asBitmap()
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .placeholder(R.drawable.user_small)
                .into(new BitmapImageViewTarget(viewHolder.friendIcon) {
                    @Override
                    protected void setResource(Bitmap resource) {

                        RoundedBitmapDrawable circularBitmapDrawable = RoundedBitmapDrawableFactory.create(getContext().getResources(), resource);
                        circularBitmapDrawable.setCircular(true);
                        viewHolder.friendIcon.setImageDrawable(circularBitmapDrawable);
                    }
                });
    }

    viewHolder.friendName.setText(element.getId());
    viewHolder.friendRank.setText(String.format("%s %d", getContext().getString(R.string.text_rank), element.getRank()));
    viewHolder.deleteFriendBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
            confirmDelete(element, position, parent);
        }
    });
    viewHolder.banFriendBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            confirmBan(element, position, parent);
        }
    });

    return convertView;
}

从朋友列表中删除用户:

        remove(element);
        notifyDataSetChanged();

你们有没有看到我做错了什么?我会非常感谢你的帮助。谢谢你:))

1 个答案:

答案 0 :(得分:8)

您正在恢复列表项(根据回收站视图的定义),这意味着如果图像设置为某个项而您没有清除它,则图像将保留在那里。因此,即使setText更改,标签viewHolder.friendIcon也不会被触及。修复非常简单:

if (element.getPhoto() != null) {
    Glide.with(getContext())...
} else {
    Glide.clear(viewHolder.friendIcon); // tell Glide that it should forget this view
    viewHolder.friendIcon.setImageResource(R.drawable.user_small); // manually set "unknown" icon
}

同时从xml中删除drawable,或者至少更改为tools:src,这将有助于缩短通胀时间;无论如何,Glide都会覆盖这个值。

为了降低复杂性,还有另一种选择:

class FriendData {
    // if you can't modify this class you can also put it in a `static String getPhotoUrl(Element)` somewhere
    public void String getPhotoUrl() {
        if (this.getPhoto() == null) return null;
        String photo = S3ImageHandler.SMALL_PROFILE_ICON_PREFIX + this.getPhoto();
        String url = String.format(S3ImageHandler.AMAZON_PROFILE_DOWNLOAD_LINK, photo);
        return url;
    }
}

然后将整个if (element.getPhoto() != null) {...}替换为:

Glide.with(getContext())
     .load(element.getPhotoUrl()) // this may be null --\
     .asBitmap() //                                     |
     .diskCacheStrategy(DiskCacheStrategy.ALL) //       |
     .placeholder(R.drawable.user_small) //             |
     .fallback(R.drawable.user_small) // <--------------/
     .into(new BitmapImageViewTarget(viewHolder.friendIcon) { ... })
;

这也会导致正确的行为,因为即使没有图像网址,Glide也会负责设置内容,请参阅JavaDoc或fallback的来源。

作为旁注,还要考虑使用CircleCrop。除了缓存优势之外,它还支持GIF,因为您可以删除.asBitmap()和自定义目标。