Recyclerview痛苦地缓慢加载毕加索的缓存图像

cha*_*dev 50 java android picasso android-5.0-lollipop android-recyclerview

我已经实现了一个RecyclerView,主要包含通过Picasso加载的图像.我的问题是,只要我向下或向上滚动视图,占位符图像就会显示约.在它被实际图像替换之前的一秒钟.它滚动非常顺利,但几乎无法使用.每次滚动屏幕时都会发生这种情况.

Picasso显然将图像缓存到磁盘,因为它们的加载速度比初始加载时间快,但它们肯定会立即从缓存中重新加载.我做错了什么?

我的适配器代码:

public class ExploreAdapter extends RecyclerView.Adapter<ExploreAdapter.ExploreViewHolder> {

    private List<ExploreItem> exploreItemList;
    private Context mContext;
    private int deviceWidth = PrefUtils.getDeviceWidth();

    public ExploreAdapter(Context context, List<ExploreItem> exploreItemList){
        this.mContext = context;
        this.exploreItemList = exploreItemList;
    }

    @Override
    public int getItemCount(){
        return exploreItemList.size();
    }

    @Override
    public void onBindViewHolder(ExploreViewHolder exploreViewHolder, int i){
        ExploreItem item = exploreItemList.get(i);
        exploreViewHolder.getvTitle().setText(item.getTitle());
        exploreViewHolder.getvUsername().setText(item.getUsername());
        exploreViewHolder.getvNumLikes().setText(item.getNbOfLikes());

        Picasso.with(mContext).load(item.getMediaLocation().trim())
                .resize(deviceWidth, deviceWidth)
                .centerCrop()
                .placeholder(R.drawable.profile_background)
                .into(exploreViewHolder.getvImage());

        Picasso.with(mContext).load(item.getUserProfilePicUrl().trim())
                .placeholder(R.drawable.profile_picture)
                .into(exploreViewHolder.getvProfilePic());
    }

    @Override
    public ExploreViewHolder onCreateViewHolder(ViewGroup viewGroup, int i){
        View itemView = LayoutInflater.
                from(viewGroup.getContext()).
                inflate(R.layout.explore_item, viewGroup, false);

        return new ExploreViewHolder(itemView);
    }

    public static class ExploreViewHolder extends RecyclerView.ViewHolder{
        private TextView  vTitle,
                          vUsername,
                          vNumLikes;

        private SquareImage vImage;
        private ImageView vProfilePic;

        public ExploreViewHolder(View v){
            super(v);
            this.vTitle = (TextView) v.findViewById(R.id.explore_item_title);
            this.vUsername = (TextView) v.findViewById(R.id.explore_item_username);
            this.vNumLikes = (TextView) v.findViewById(R.id.explore_item_number_likes);
            this.vImage = (SquareImage) v.findViewById(R.id.explore_item_image);
            this.vProfilePic = (ImageView) v.findViewById(R.id.explore_item_profile_picture);
        }

        public TextView getvTitle() {
            return vTitle;
        }

        public TextView getvUsername() {
            return vUsername;
        }

        public ImageView getvProfilePic() {
            return vProfilePic;
        }

        public SquareImage getvImage() {
            return vImage;
        }

        public TextView getvNumLikes() {
            return vNumLikes;
        }

        public void setvImage(SquareImage vImage) {
            this.vImage = vImage;
        }

        public void setvNumLikes(TextView vNumLikes) {
            this.vNumLikes = vNumLikes;
        }

        public void setvProfilePic(ImageView vProfilePic) {
            this.vProfilePic = vProfilePic;
        }

        public void setvTitle(TextView vTitle) {
            this.vTitle = vTitle;
        }

        public void setvUsername(TextView vUsername) {
            this.vUsername = vUsername;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

任何帮助表示赞赏.

erg*_*cak 68

设置recyclelerView参数如下解决了我的口吃问题:

recyclerView.setHasFixedSize(true);
recyclerView.setItemViewCacheSize(20);
recyclerView.setDrawingCacheEnabled(true);
recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
Run Code Online (Sandbox Code Playgroud)

我希望它也可以帮助别人.

  • 这是一个很好的解决方案. (3认同)
  • 这对我也有用.但我只使用你的2行和3行代码) (2认同)
  • 用recyclerview滞后卷轴解决了我的问题,非常感谢. (2认同)
  • 这不是可扩展的解决方案并且违背了回收者视图的目的 (2认同)
  • recyclerView.setDrawingCacheEnabled(true); 已被废弃 (2认同)

Man*_*esh 27

使用fit().

Picasso.with(context)
        .load(file)
        .fit()
        .centerCrop()
        .into(imageView);
Run Code Online (Sandbox Code Playgroud)

fit()实际调整大小以适应该图像imageView的边界.这不会加载完整的图像并使滚动变得平滑.

  • 试过 `.fit()` 但 `.resize().centerCrop()` 效果更好。更快的结果。 (2认同)

小智 8

我把@ergunkocak和@Mangesh Ghotage的答案混合在一起,用这个很好:

recyclerView.setHasFixedSize(true);
recyclerView.setItemViewCacheSize(20);
recyclerView.setDrawingCacheEnabled(true);
Run Code Online (Sandbox Code Playgroud)

这在每个图像上:

Picasso.with(context)
        .load(file)
        .fit()
        .into(imageView);
Run Code Online (Sandbox Code Playgroud)

除了你可以设置Picasso使用这样的单个实例:

Picasso.setSingletonInstance(picasso);
Run Code Online (Sandbox Code Playgroud)

最后启用缓存指示器将为您提供有关出错的线索:

Picasso  
    .with(context)
    .setIndicatorsEnabled(true);
Run Code Online (Sandbox Code Playgroud)

更多关于毕加索的信息


Jor*_*ito 1

我无法验证这个解决方案的正确性,但我也面临这个问题,并按照这个想法解决它:

@Override
public void onBindViewHolder(ViewHolder viewHolder, final int i) {

...

    if(mImageView.getDrawable() == null)
         Picasso.with(context)
            .load(path)
            .error(errorResId)
            .tag(tag)
            .into(mImageView);
...  
}
Run Code Online (Sandbox Code Playgroud)

它的目的是禁止 Picasso 加载任何内容,除非 ImageView 没有任何内容可显示。

  • 我认为这行不通。当然,适用于 RecyclerView 中的第一个元素,但对于所有其他元素,将显示相同的图像。 (4认同)