web-dev-qa-db-fra.com

Adaptateur Recyclerview et Glide - même image tous les 4-5 rangs

J'ai ce problème - juste à des fins de test, j'ai ajouté ParseFile à l'un des ParseObject de la liste reçue. Au lieu de ne l'indiquer que dans cette ligne, il affiche toutes les 4 ou 5 lignes, parfois plus, parfois moins. Je pense que le recyclage a quelque chose à voir avec cela. Étrangement, d'autres données (supprimées de cet exemple) fonctionnent bien avec la variable position.

@Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        if(parseList.get(position).get("logo") != null){
            ParseFile image = (ParseFile) parseList.get(position).get("logo");
            String url = image.getUrl();
            Glide.with(context)
                    .load(url)
                    .placeholder(R.drawable.piwo_48)
                    .transform(new CircleTransform(context))
                    .into(holder.imageView);


        }

    }
35
jean d'arme

Les réponses ici sont incorrectes, même si elles sont sur la bonne voie.

Vous devez appeler Glide#clear(), et non simplement définir l’image dessinable sur null. Si vous n'appelez pas clear(), une charge asynchrone dont le traitement est en panne peut entraîner des problèmes de recyclage de la vue. Votre code devrait ressembler à ceci:

@Override 
public void onBindViewHolder(ViewHolder holder, int position) {
    if (parseList.get(position).get("logo") != null) {
        ParseFile image = (ParseFile) parseList.get(position).get("logo");
        String url = image.getUrl();
        Glide.with(context) 
                .load(url)
                .placeholder(R.drawable.piwo_48)
                .transform(new CircleTransform(context)) 
                .into(holder.imageView);
    } else {
        // make sure Glide doesn't load anything into this view until told otherwise
        Glide.clear(holder.imageView);
        // remove the placeholder (optional); read comments below
        holder.imageView.setImageDrawable(null);
    }
} 
73
Sam Judd

Peut-être que vous devez essayer quelque chose comme ça

.signature(new StringSignature(String.valueOf(System.currentTimeMillis())))

échantillon :

Glide.with(context)
                .load(url)
                .placeholder(R.drawable.progress_animation)
                .crossFade()
                .signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
                .error(R.drawable.image_error_404)
                .into(iv);
2
Aleksey Timoshchenko

Dans RecyclerView, chaque ligne est recyclée avec de nouvelles données. Dans votre code, vous définissez ImageView uniquement lorsqu'il ne s'agit pas de null et sinon, vous ne faites rien. Dans ce cas, lorsque ce n'est pas nul, ImageView affichera l'ancienne image car vous n'avez pas override pour l'objet actuel. Vous pouvez résoudre ce problème en ajoutant une autre condition et en définissant ImageView sur rien/null.

@Override 
    public void onBindViewHolder(ViewHolder holder, int position) {
        if(parseList.get(position).get("logo") != null){
            ParseFile image = (ParseFile) parseList.get(position).get("logo");
            String url = image.getUrl();
            Glide.with(context) 
                    .load(url)
                    .placeholder(R.drawable.piwo_48)
                    .transform(new CircleTransform(context)) 
                    .into(holder.imageView);


        } 
        else{
            holder.imageView.setImageDrawable(null);
        }
    } 
1
Sharj

Je pense que c'est parce que votre adaptateur a adapter.setHasStableIds (true) est vrai et getItemId n'est pas remplacé. Donc, recyclerView essaie de trouver un titulaire avec le même identifiant et de le réutiliser.

1
Pavlo Zorya

Lorsque "logo" est nul, vous obtenez l'image recyclée au lieu de l'effacer. Ajoutez ce code pour effacer correctement l'image:

holder.imageView.setImageDrawable(null);
1
BladeCoder