Glide和RecyclerView - 图像搞砸了

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Glide和RecyclerView - 图像搞砸了相关的知识,希望对你有一定的参考价值。

我正在尝试使用ImageViews创建RecyclerView。这是我得到的:

enter image description here

正如你所看到的,所有的艺术家封面都搞砸了,而且顺序错了。如果我滚动或重新加载,相应的图像可能会更改。

这是我的适配器onBindViewHolder:

public class ArtistsAdapter extends RecyclerView.Adapter<ArtistViewHolder> implements ListPreloader.PreloadModelProvider 
    private static final String TAG = ArtistsAdapter.class.getSimpleName();
    private final LayoutInflater mInflater;
    private final GlideRequest<Bitmap> fullRequest;

    ArtistsAdapter(Context context) 
        this.mContext = context;
        this.artists = new ArrayList<>();
        this.mInflater = LayoutInflater.from(context);
        this.fullRequest = GlideApp.with(context).asBitmap();
    

    private final Context mContext;

    public List<CompactdArtist> getArtists() 
        return artists;
    

    void swapArtists (List<CompactdArtist> artists) 
        this.artists.clear();
        this.artists.addAll(artists);
        notifyDataSetChanged();
    

    private final List<CompactdArtist> artists;

    @Override
    public ArtistViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
        View view = mInflater.inflate(R.layout.recyclerview_artist_item, parent, false);
        return new ArtistViewHolder(view);
    

    @Override
    public void onViewRecycled(ArtistViewHolder holder) 
        super.onViewRecycled(holder);
        Log.d(TAG, "onViewRecycled: ");
        GlideApp.with(mContext).clear(holder.artistImageView);
        holder.artistImageView.setImageDrawable(null);
    

    @Override
    public void onBindViewHolder(final ArtistViewHolder holder, final int position) 
        Log.d(TAG, "onBindViewHolder: " + position);
        final CompactdArtist current = artists.get(position);

        // holder.setIsRecyclable(false);

        holder.artistImageView.setImageDrawable(null);
        try 
            fullRequest.load(new MediaCover(current))
                .fallback(ImageUtils.getFallback(mContext))
                .into(new ImageViewTarget<Bitmap>(holder.artistImageView) 
                    @Override
                    protected void setResource(@Nullable Bitmap resource) 
                        if (resource == null) 
                            // holder.setIsRecyclable(true);
                            return;
                        

                        holder.artistImageView.setImageBitmap(resource);
                        int color = Palette.from(resource).generate().getMutedColor(0xFFFFFF);
                        try 
                            current.fetch();
                         catch (CouchbaseLiteException e) 
                            e.printStackTrace();
                            holder.artistNameText.setText(R.string.unknown_artist_name);
                        
                        holder.artistBackground.setBackgroundColor(color);
                        holder.bindArtist(current);
                        holder.artistSub.setText(current.getAlbumCount() + " albums");
                        holder.artistNameText.setText(current.getName());

                        // holder.setIsRecyclable(true);
                    

                    @Override
                    public void onLoadCleared(@Nullable Drawable placeholder) 
                        super.onLoadCleared(placeholder);
                        // holder.setIsRecyclable(true);
                    
                );
         catch (IOException e) 
            e.printStackTrace();
        
    

    @Override
    public long getItemId(int position) 
        return artists.get(position).getId().hashCode();
    

    @Override
    public int getItemCount() 
        return this.artists.size();
    

    @NonNull
    @Override
    public List getPreloadItems(int position) 
        return this.artists.subList(position, position + 1);
    

    @Nullable
    @Override
    public RequestBuilder<?> getPreloadRequestBuilder(Object item) 
        MediaCover cover = (MediaCover) item;
        return fullRequest.clone().thumbnail(0.2f).load(cover);
    

这是我的片段容器中的代码:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 

    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_artists, container, false);

    mArtistRecyclerView = rootView.findViewById(R.id.artists_recyclerview);

    LinearLayoutManager layoutManager = new GridLayoutManager(getContext(), 3);
    mArtistRecyclerView.setLayoutManager(layoutManager);

    mArtistsAdapter = new ArtistsAdapter(getActivity());
    mArtistRecyclerView.setAdapter(mArtistsAdapter);
    mArtistRecyclerView.setRecyclerListener(new RecyclerView.RecyclerListener() 
        @Override
        public void onViewRecycled(RecyclerView.ViewHolder holder) 
            ArtistViewHolder artistViewHolder = (ArtistViewHolder) holder;
            GlideApp.with(holder.itemView).clear(artistViewHolder.getArtistImage());
        
    );
    FixedPreloadSizeProvider<MediaCover> coverSizeProvider = new FixedPreloadSizeProvider<>(64, 64);
    RecyclerViewPreloader<MediaCover> preloader = new RecyclerViewPreloader<MediaCover>(GlideApp.with(this), mArtistsAdapter, coverSizeProvider, 2);

    return rootView;

作为奖励,我为我的MediaCover添加了抓取器:

/**
 * Created by vinz243 on 13/12/2017.
 */

public class MediaCoverFetcher implements DataFetcher<InputStream> 
    private final MediaCover mediaCover;
    private boolean cancelled = false;
    private InputStream stream;

    public MediaCoverFetcher(MediaCover mediaCover) 
        this.mediaCover = mediaCover;
    

    @Override
    public void loadData(Priority priority, DataCallback<? super InputStream> callback) 
        CompactdArtwork artwork = mediaCover.getArtwork();
        try 
            stream = artwork.getImage(ArtworkSize.LARGE);
            if (cancelled) 
                callback.onLoadFailed(new RuntimeException("Cancelled"));
             else 
                callback.onDataReady(stream);
            
         catch (NullPointerException e) 
            callback.onLoadFailed(e);
        
    

    @Override
    public void cleanup() 
        if (stream != null) 
            try 
                stream.close();
             catch (IOException e) 
                e.printStackTrace();
            
        
    

    @Override
    public void cancel() 
        cancelled = true;
    

    @NonNull
    @Override
    public Class<InputStream> getDataClass() 
        return InputStream.class;
    

    @NonNull
    @Override
    public DataSource getDataSource() 
        return DataSource.LOCAL;
    


我想它来自回收部分,但我不知道如何解决这个问题。正如您在代码中看到的那样,我尝试了setIsRecyclable,但是我会收到错误,说出无法匹配的调用,而且它无法修复它

答案

你应该尝试改变一些事情:

  • 在setResource函数中移动ArtistViewHolder对象上的setter
  • 将您的CompactdArtist变量定义为final @Override public void onBindViewHolder(final ArtistViewHolder holder, int position) Log.d(TAG, "onBindViewHolder: " + position); final CompactdArtist current = artists.get(position); // holder.setIsRecyclable(false); holder.bindArtist(artists.get(position)); holder.artistImageView.setImageDrawable(null); try current.fetch(); fullRequest.load(new MediaCover(current)) .fallback(ImageUtils.getFallback(mContext)) .into(new ImageViewTarget<Bitmap>(holder.artistImageView) @Override protected void setResource(@Nullable Bitmap resource) if (resource == null) // holder.setIsRecyclable(true); return; holder.artistImageView.setImageBitmap(resource); int color = Palette.from(resource).generate().getMutedColor(0xFFFFFF); holder.artistBackground.setBackgroundColor(color); // holder.setIsRecyclable(true); holder.artistNameText.setText(current.getName()); holder.artistSub.setText(current.getAlbumCount() + " albums"); @Override public void onLoadCleared(@Nullable Drawable placeholder) super.onLoadCleared(placeholder); // holder.setIsRecyclable(true); ); catch (CouchbaseLiteException e) e.printStackTrace(); holder.artistNameText.setText(R.string.unknown_artist_name); catch (IOException e) e.printStackTrace();

我假设您加载图像的方式是异步的,因此在这种情况下,您的问题在于您将变量设置为同步过程,这就是为什么您将信息显示在错误的块上。

以上是关于Glide和RecyclerView - 图像搞砸了的主要内容,如果未能解决你的问题,请参考以下文章

Glide 是不是对每个图像请求进行排队?滚动时Recyclerview加载非常慢

我一起使用 Glide 和 RecyclerView 但它没有按我的意愿滚动

RecyclerView + Glide 显示结果一团糟

如何事先获取将存储在 Android/Java 缓存中的未来 Glide 图像大小?

在全屏android中使用recyclerview幻灯片图像

缩略图在 RecyclerView (Android) 中保持空白。我正确使用 Glide 吗?