24

私はこの問題を抱えています。テスト目的のために、ParseFileParseObjectのいずれかに追加しました。その行にのみ表示するのではなく、4〜5行ごとに表示します。私はリサイクル・ビューにこれと関係があることを認めています。不思議なことに、他のデータ(この例から削除)はposition変数で正常に動作します。Recyclerviewアダプタとグライド - 4-5行ごとに同じイメージ

@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); 


     } 

    } 

答えて

49

正しい回答はありますが、ここの回答は間違っています。

イメージドロアブルをnullに設定するだけでなく、Glide#clear()に電話する必要があります。 clear()に電話をかけると、非同期ロードが異常終了しても、ビューの再利用に関する問題が発生する可能性があります。あなたのコードは次のようになります。

@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); 
    } 
} 
+0

あなたはそれについてもっと詳しく説明できますか?これまでの答えはうまくいきましたが、 'clear() 'メソッドは薄い空気から実装されていないと思います。 –

+0

彼らはほとんど仕事をしています。 onBindViewHolderを呼び出して、指定されたビューのロゴのある位置のロードを開始し、ロードが完了する前に同じViewHolderでonBindViewHolderを再度呼び出すと、空のビューの代わりに古いイメージが表示されます。この競合状態は以前のエラーよりもはるかに一般的ではありませんが、依然として可能です。 –

+0

また、私はライブラリとclear()メソッドを書いたことを明確にする必要があります。このユースケースは、clear()メソッドが存在する理由の素晴らしい例です。新しいロードを開始する(古いロードをキャンセルする)か、ビューを再利用しているときに自分自身でロードをキャンセルする必要があります。 –

1

"ロゴ"がnullの場合は、リサイクルされたイメージが表示されます。適切に画像をクリアするためにこのコードを追加:RecyclerView

holder.imageView.setImageDrawable(null); 
1

各行が新しいデータで再循環されます。あなたのコードではnullでない場合にのみImageViewを設定し、それ以外は何もしません。この場合、nullでない場合ImageViewは、現在のオブジェクトのoverrideではないため、古いイメージを表示します。これを修正するには、else条件を追加し、ImageViewにnull/blankを設定します。

@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

私はそれがビューのリサイクルで何かだということを知っていたが、思ったことはありませんそのようにありがとう、これはすぐに働いた:) –

+0

この回答は不完全です。また、問題の画像ビューでGlide.clear()を呼び出す必要があります。そうしないと、後で非同期ロードが完了したときにセルの再利用の問題が発生することがあります。 –

+0

@samajudd私はちょうどそれを見つけたので、 'setImageDrawable(null)'と 'Glide.clear()'の両方を呼び出す必要がありますか? –

2

たぶん、あなたはこの

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

ような何かをしようとする必要があるサンプル:

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);