Android,RecyclerView:加载了正确的视图,但在错误的位置膨胀



我正在制作一款在手机上播放音乐文件的应用程序。它在回收器视图中列出了所有歌曲及其艺人名称、歌曲名称和专辑封面(如果可用(。

一切都很顺利,直到我试着装上专辑封面。一开始(在我滚动之前(一切看起来都很好,但滚动一段时间后,封面开始出现在不应该出现的地方。假设我刚刚看到了歌曲X的专辑封面,然后滚动一些之后,歌曲X的同一封面出现在歌曲y旁边。这尤其是wierd,因为它确实正确加载了专辑名称和其他所有内容。它只是混淆了位图。这就是我初始化回收器视图的方式:

private async Task InitRecView()
{
await Task.Run(() =>
{
// Instantiate the adapter and pass in its data source:
LinearLayout lnBg = (LinearLayout)FindViewById(Resource.Id.background_recView);
mAdapter = new PhotoAlbumAdapter(GetSortedListWithAllSongs(), this, dbSeekObj, seekObj, mAudioManager, this, lnBg);
// Get our RecyclerView layout:
mRecyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView);
// Plug the adapter into the RecyclerView:
mRecyclerView.SetAdapter(mAdapter);
mRecyclerView.SetItemViewCacheSize(15);
mRecyclerView.DrawingCacheEnabled = true;
mRecyclerView.DrawingCacheQuality = DrawingCacheQuality.High;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.SetLayoutManager(mLayoutManager);
});
}

这是我的适配器,我在其中检索数据(问题可能发生在"SetContentAsync(("中

public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From(parent.Context).
Inflate(Resource.Layout.CardView, parent, false);
PhotoViewHolder vh = new PhotoViewHolder(itemView, mp3Obj, act, reader, db, seekObj, audioManager, lnBg, ctx);
return vh;
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
PhotoViewHolder vh = holder as PhotoViewHolder;
SetContent(vh, position);
}
private async void SetContent(PhotoViewHolder vh, int position)
{
await SetContentAsync(vh, position);
}

private async Task SetContentAsync(PhotoViewHolder vh, int position)
{
string SongName = "";
string ArtistName = "";
Bitmap bitmap = null;
byte[] data = null;
try
{
reader.SetDataSource(mp3Obj[position].Mp3Uri);
}
catch { }

await Task.Run(() => // cause problems with the reload
{
SongName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle);
ArtistName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist);
data = reader.GetEmbeddedPicture();
if (data != null)
{
bitmap = BitmapFactory.DecodeByteArray(data, 0, data.Length);
}
});
((Activity)ctx).RunOnUiThread(() =>
{
vh.SongName.SetTypeface(tf, TypefaceStyle.Normal);
vh.AristName.SetTypeface(tf, TypefaceStyle.Normal);
vh.SongName.Text = SongName;
vh.AristName.Text = ArtistName;
if (bitmap != null)
{
ConvertBitmapToBackground(bitmap, vh); // Set As Backgorund, blurry and black ( just sets the variable)
CutImageIntoForm(bitmap, vh); // Set as the musical note button
}
});

}

这就是视图持有者,在这里除了初始化视图之外什么都没发生:

public PhotoViewHolder(View itemView, List<MP3objectSmall> mp3Obj, Activity act, MediaMetadataRetriever reader, DataBase db, List<SeekObj> seekObj, AudioManager audioManager, LinearLayout lnBg, Context ctx) : base(itemView)
{
// Locate and cache view references:
SongName = itemView.FindViewById<TextView>(Resource.Id.textView);
AristName = itemView.FindViewById<TextView>(Resource.Id.textView2);
lnContainer = itemView.FindViewById<LinearLayout>(Resource.Id.linlay_cardview);
CoverArt = itemView.FindViewById<ImageButton>(Resource.Id.musical_note);
this.mp3Obj = mp3Obj;
this.act = act;
this.reader = reader;
this.db = db;
this.seekObj = seekObj;
this.ctx = ctx;
this.audioManager = audioManager;
this.lnBg = lnBg;

lnContainer.Click += delegate
{
int pos = AdapterPosition;
ClickEvent(pos, AristName.Text, SongName.Text, CoverArt, lnBg);
};
}

如果有人能帮我的话。为什么我的回收器视图会混淆位图,并将它们放入错误的布局和/或加倍?

谢谢!

编辑:

我注意到,相同项目的重复出现总是在相同的时间间隔内发生。对我来说,每24个项目都包含项目24在该项目之前的位置的图像。我还读到,这是因为回收者的观点是回收者说的观点,但我不明白的是,如何发现一件物品是否被回收,何时被回收,只需使用新的数据。。。

由于您使用异步方法,所以难怪它会显示旧数据。在viewHolder中创建clear方法,并在onViewRecycledMethod:中调用它

public class TextRecyclerAdapter extends RecyclerView.Adapter<TextRecyclerAdapter.TextViewHolder> {
...        
@Override
public void onViewRecycled(@NonNull TextViewHolder holder) {
//clear your view here
holder.clear();
}
....
public static class TextViewHolder extends RecyclerView.ViewHolder {    
...
public void clear(){
//clear your view here
_textView.setText("");
}
private TextView _textView;
...    
}

更新这也可能发生,因为异步调用中的旧数据晚于新数据。您需要使用取消令牌取消回收中的旧请求。

最新更新