Search code examples
androidandroid-recyclerviewrealmrealm-mobile-platform

Auto-updating RealmRecyclerViewAdapter displays incorrect data on update


I'm using a RealmRecyclerViewAdapter to hold a collection of Series objects, which have images associated with them. When I refresh the Series data (via API), the adapter auto-updates as I expect but the displayed images are changed and are incorrect. Through my testing I've noticed that setting auto-update to false via the RealmRecyclerViewAdapter constructor stops this behavior, so the refreshing of the list items is causing this to happen. Also if I leave auto-update to true, and I set a breakpoint during the calls to onBindViewHolder, the images are still correct. Running the code without breakpoints (at full speed) will cause incorrect images to be displayed. The strange this is that ONLY the images are incorrectly displayed after an update. Any text is still accurate.

Here is a GIF displaying this behavior. As you can see, when I refresh the data, the rows are updated and the incorrect images are displayed.

https://gyazo.com/88d5735796770b1573bdd518ce53ed44

Here is a snippet of onBindViewHolder where the row's images are set:

public void onBindViewHolder(ViewHolder holder, int position) {
    final int adapterPosition = holder.getAdapterPosition();
    holder.series = getItem(adapterPosition);

    final String MALID = holder.series.getMALID();

    ...

    int imageId = App.getInstance().getResources().getIdentifier("malid_" + holder.series.getMALID(), "drawable", "<app-package>");
    if (imageId != 0) {
        Picasso.with(App.getInstance()).load(imageId).fit().centerCrop().into(holder.mPoster);
    } else {
        File cacheDirectory = App.getInstance().getCacheDir();
        File bitmapFile = new File(cacheDirectory, holder.series.getMALID() + ".jpg");

        Picasso.with(App.getInstance()).load(bitmapFile).placeholder(R.drawable.placeholder).fit().centerCrop().into(holder.mPoster);
    }

    holder.mAddButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            addSeriesHelper(MALID);
        }
    });
    holder.mMinusButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            RemoveSeriesDialogFragment dialogFragment = RemoveSeriesDialogFragment.newInstance(self, MALID, adapterPosition);
            dialogFragment.show(seriesFragment.getMainActivity().getFragmentManager(), TAG);
        }
    });
}

I first check the app resources if it contains an anime for the Series. If not, it will check if a cached version is available.


Solution

  • if (!(photoPath.isEmpty())) {
    
                int defaultImagePath = R.drawable.default_thumb;
                int errorImagePath = R.drawable.damaged_image;
                holder.mImageView.setImageResource(defaultImagePath);
    
                String uri = photoPath;
                loadImageWithGlide(mContext, holder.mImageView, uri, defaultImagePath,
                        errorImagePath);
            }
    
    
            public static void loadImageWithGlide(final Context context, ImageView theImageViewToLoadImage,
                                              String theLoadImagePath, int theDefaultImagePath, int tehErrorImagePath) {
            if (context == null) return;
    
            //placeHolderUrl=R.drawable.ic_user;
            //errorImageUrl=R.drawable.ic_error;
            Glide.with(context) //passing context
                    .load(theLoadImagePath) //passing your url to load image.
                    .placeholder(theDefaultImagePath) //this would be your default image (like default profile or logo etc). it would be loaded at initial time and it will replace with your loaded image once glide successfully load image using url.
                    .error(tehErrorImagePath)//in case of any glide exception or not able to download then this image will be appear . if you won't mention this error() then nothing to worry placeHolder image would be remain as it is.
                    .diskCacheStrategy(DiskCacheStrategy.ALL) //using to load into cache then second time it will load fast.
                    //.animate(R.anim.fade_in) // when image (url) will be loaded by glide then this face in animation help to replace url image in the place of placeHolder (default) image.
                    .fitCenter()//this method help to fit image into center of your ImageView
                    .into(theImageViewToLoadImage); //pass imageView reference to appear the image.
    
        }
    
        add dependencies inside app build.gralde.
         // glide
        compile 'com.github.bumptech.glide:glide:3.7.0'