【问题标题】:Glide and RecyclerView - Images messed upGlide 和 RecyclerView - 图像混乱
【发布时间】:2017-12-14 16:29:53
【问题描述】:

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

如您所见,所有艺术家的封面都乱七八糟且顺序错误。如果我滚动或重新加载,相应的图像可能会改变。

这是我的适配器 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 添加了 fetcher:

/**
 * 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,但我会收到错误,说不匹配的调用,它不会修复它

【问题讨论】:

    标签: android android-recyclerview android-glide


    【解决方案1】:

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

    • 在 setResource 函数中将设置器移到 ArtistViewHolder 对象上
    • 将您的 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();
       }
      }
      

    我假设您加载图像的方式是异步的,因此在这种情况下,您的问题在于您将变量设置为就好像它们处于同步过程中一样,这就是您将信息显示在错误块上的原因.

    【讨论】:

    • 更正,它不再起作用-_-,用新代码编辑帖子
    • 好吧,通常你不会在回答后编辑你问题的所有代码,因为人们不会理解我为什么回答这个问题^^'但是好的,我会看看我是否找到为什么它仍然不起作用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-15
    • 2023-03-21
    • 1970-01-01
    相关资源
    最近更新 更多