這個(gè)bug可以說(shuō)是折磨了我很久了,問(wèn)了人,查了博客,最后找到了答案。
首先要搞明白R(shí)ecyclerView中的ViewHolder的復(fù)用機(jī)制是什么,在,以及由于復(fù)用機(jī)制和請(qǐng)求網(wǎng)絡(luò)mix在一起之后會(huì)發(fā)生哪些可能的事故,強(qiáng)烈推薦一個(gè)好文:
他的博客取來(lái)的圖片
總結(jié)一下就是:
- RecyclerView用的是我們自定義的內(nèi)部類(lèi)ViewHolder來(lái)復(fù)用的,也就是復(fù)用的是ViewHoler
- 當(dāng)屏幕下滑,item1滑出可視區(qū)域,將item1的ViewHolder對(duì)象給item8復(fù)用,那么此時(shí)item1中ViewHolder對(duì)象中持有的變量都是item1的。
- item1中的ViewHolder對(duì)象,在onBindViewHolder(MyViewHolder holder, int position)方法中對(duì)holder進(jìn)行更新,但是如果在這里調(diào)用glide去從url加載圖片到holder中的imageView對(duì)象的話(huà),就有可能因?yàn)榫W(wǎng)絡(luò)延遲,導(dǎo)致圖片加載不出來(lái),那么item8就會(huì)先顯示item1的圖片,過(guò)一會(huì)延遲之后,顯示正確的item8該顯示的圖片
上面博客加載圖片用的是AsynTask,我用的是Glide框架,ViewHolder中3個(gè)TextView,一個(gè)ImageView,按照那個(gè)思路,我的處理方法如下:
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
if (holder == null) {
return;
}
holder.tvDesc.setText(resultsBeanList.get(position).getDesc());
holder.tvPublishedAt.setText(timeParse.getTime(resultsBeanList.get(position).getPublishedAt()));
Object who = resultsBeanList.get(position).getWho();
if (who != null) {
holder.tvWho.setText((String) who);
}else {
//防止ViewHolder復(fù)用導(dǎo)致上一個(gè)tvWho的內(nèi)容遺留
holder.tvWho.setText("");
}
//處理imageView--------------
List<String> imagesUrl = resultsBeanList.get(position).getImages();
if (imagesUrl == null) {
//當(dāng)ViewHolder復(fù)用的時(shí)候,如果當(dāng)前返回的圖片url為null,為了防止上一個(gè)復(fù)用的viewHolder圖片
//遺留,要clear并且將圖片設(shè)置為空。
Glide.with(fragment).clear(holder.ivImage);
holder.ivImage.setImageDrawable(null);
holder.ivImage.setTag(R.id.image_tag, position);
return;
}
Object tag=holder.ivImage.getTag(R.id.image_tag);
if (tag!=null&&(int) tag!= position) {
//如果tag不是Null,并且同時(shí)tag不等于當(dāng)前的position。
//說(shuō)明當(dāng)前的viewHolder是復(fù)用來(lái)的
//Cancel any pending loads Glide may have for the view
//and free any resources that may have been loaded for the view.
Glide.with(fragment).clear(holder.ivImage);
}
String url = imagesUrl.get(0);
Glide.with(fragment)
.load(url + "?imageView2/0/w/100")
.apply(options)
.into(holder.ivImage);
//給ImageView設(shè)置唯一標(biāo)記。
holder.ivImage.setTag(R.id.image_tag, position);
}
至此,不再圖片混亂。