Glide 用加载的图像部分覆盖屏幕

Glide overlays screen with loaded image parts

由于我在互联网上找不到任何相关内容,这将是我的第一个 SO 问题:

问题描述

我遇到了以下问题:
在我的应用程序中,我有一个 RecyclerView 和一个 GridLayoutManager,它显示由 Glide 加载的图像。

缓慢滚动时一切正常。

快速上下滚动后(更进一步可以称之为"abuse of scrolling")一些图像部分或整个图像将随机覆盖我的屏幕,因此下面的内容不再可见。在屏幕边缘尤其如此。

出现上述错误的测试设备为一加一运行CM12.1.1(Android5.1.1)。我没有在其他设备上测试。

感谢任何关于为什么会发生这种情况或如何解决它的提示/帮助/解释。

代码

下面是带有内部 ViewHolder 的 Adapter 的代码 class:

public class PhotoListAdapter extends RecyclerView.Adapter<PhotoListAdapter.PhotoHolder>{

  private ArrayList<PhotoDetail> mPhotos;
  private String mAccessToken;
  private int mUserId;
  private int mPageCounter = 1;
  private boolean mIsLoading = false;
  private boolean mEndReached = false;


  public PhotoListAdapter (String accessToken, int userId){
    mPhotos = new ArrayList<>();
    mAccessToken = accessToken;
    mUserId = userId;
    fetchPhotos();
  }

  @Override
  public PhotoHolder onCreateViewHolder(ViewGroup parent, int viewType) {
      View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_photo_list_item, parent, false);
      PhotoHolder photoHolder = new PhotoHolder(itemView);
      return photoHolder;
  }

  @Override
  public void onBindViewHolder(PhotoHolder holder, int position) {
      holder.bind(mPhotos.get(position));
      if (position == mPhotos.size() - 6) fetchPhotos();
  }

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

  public void fetchPhotos () {
      if (mIsLoading || mEndReached) return;
      else {
          mIsLoading = true;
          //Retrofit call which will return a JSON Object with the Photo Details, like the filename
          // With this information i can build the URL of the image
          ApiProvider.getInstance().getApi().getPhotos(mUserId, mAccessToken, "time", "all", mPageCounter, mUserId, 32).enqueue(new Callback<PhotoResponseWrapper>() {
              @Override
              public void onResponse(Call<PhotoResponseWrapper> call, Response<PhotoResponseWrapper> response) {
                  if (response.code() == HttpURLConnection.HTTP_OK){
                      int photoCount = response.body().getPhotoResponse().getPhotosCount();
                      if (photoCount != 32) mEndReached = true;
                      Collections.addAll(mPhotos, response.body().getPhotoResponse().getPhotos());
                      notifyItemRangeInserted(mPhotos.size() - photoCount,photoCount);
                      mPageCounter++;
                  }
                  mIsLoading = false;
              }

              @Override
              public void onFailure(Call<PhotoResponseWrapper> call, Throwable t) {
                  mIsLoading = false;
              }
          });
      }
  }

  class PhotoHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

      private ImageView mPhotoView;
      private PhotoDetail mPhotoDetail;

      public PhotoHolder(View itemView) {
          super(itemView);
          mPhotoView = (ImageView) itemView.findViewById(R.id.img_photo);
          mPhotoView.setOnClickListener(this);
      }

      public void bind (PhotoDetail photoDetail){
          mPhotoDetail = photoDetail;

          String photoUrl = Api.Endpoints.PHOTOS_SMALL + photoDetail.getUserId() + '/' + photoDetail.getFileName();
          mPhotoView.setContentDescription(photoDetail.getDescription());
          // First stop all pending image loads
          Glide.clear(mPhotoView);
          // Then load new url
          Glide.with(mPhotoView.getContext())
                  .load(photoUrl)
                  .into(mPhotoView);
      }

      @Override
      public void onClick(View v) {

      }
  }
}

下面是单个项目的XML:

<?xml version="1.0" encoding="utf-8"?>
<ImageView
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/img_photo"
  android:clickable="true"
  android:layout_width="match_parent"
  android:layout_height="@dimen/height_photo_item"
  android:padding="@dimen/padding_photo_item"
  android:scaleType="centerCrop"/>

下面是 RecyclerView 的 XML:

<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/layout_swipe_refresh"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingRight="@dimen/padding_photo_item"
  android:paddingLeft="@dimen/padding_photo_item"
  android:paddingTop="@dimen/padding_photo_item"
  tools:context=".fragments.PhotoListFragment">
  <android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>

例子

错误的一些视觉示例是这些屏幕截图:

因为我找不到任何关于如何解决这个问题的信息,我尝试了主要的替代图像加载和缓存库 - Picasso
使用这个库,上面提到的错误对我来说是不可重现的,所以我猜它真的是 Glide 特定的。

您必须使用占位符图像。

Glide.with(mPhotoView.getContext())
.load(photoUrl)
.placeholder(R.drawable.image_placeholder) // Your placeholder image
.into(mPhotoView);

我遇到了同样的问题,设置占位符为我解决了这个问题。