在我的应用程序中,我有一个(在我的手机上)包含大约700首歌曲名称和乐队名称的RecyclerView。没有什么太疯狂的,但在UI线程上重新加载所有这些都会导致一些延迟。我决定在一个异步任务中加载,而不是UI线程。它看起来是这样的:
public class PhotoAlbumAdapter : RecyclerView.Adapter
{
public List<MP3objectSmall> mp3Obj;
Context ctx;
Activity act;
MediaMetadataRetriever reader;
DataBase db;
List<SeekObj> seekObj;
Typeface tf;
AudioManager audioManager;
public PhotoAlbumAdapter(List<MP3objectSmall> mp3Obj, Context ctx, DataBase db, List<SeekObj> seekObj, AudioManager audioManager, Activity act)
{
this.mp3Obj = mp3Obj;
this.ctx = ctx;
this.db = db;
this.seekObj = seekObj;
this.act = act;
this.audioManager = audioManager;
reader = new MediaMetadataRetriever();
tf = Typeface.CreateFromAsset(ctx.Assets, "Baiti.ttf");
}
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, 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);
}
public override int ItemCount
{
get
{
if (mp3Obj != null)
{
return mp3Obj.Count();
}
else
return 0;
}
}
private async Task SetContentAsync(PhotoViewHolder vh, int position)
{
string SongName = "";
string ArtistName = "";
await Task.Run(() =>
{
try
{
reader.SetDataSource(mp3Obj[position].Mp3Uri);
}
catch
{
}
SongName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle);
ArtistName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist);
});
((Activity)ctx).RunOnUiThread(() =>
{
vh.SongName.SetTypeface(tf, TypefaceStyle.Normal);
vh.AristName.SetTypeface(tf, TypefaceStyle.Normal);
vh.SongName.Text = SongName;
vh.AristName.Text = ArtistName;
});
}
}事实上,这确实使整体性能提高了很多,但也造成了一些奇怪的副作用:
当我快速地向下滚动列表,然后突然停止时,我会连续看到同一首歌2-3次。这些项目中只有一项是歌曲本身,其他是不同的歌曲,但在它们上面有错误的歌曲和艺术家的名字。
如果我现在稍微向上滚动,使加倍的项目从屏幕上消失,然后向后滚动,RecyclerView似乎已经进行了自我修正,而加倍或有时是三倍的项目消失了。
此问题仅在我将加载移动到异步任务后才会发生。我是不是做错了什么?
发布于 2018-11-21 22:12:29
我认为这里的重点是保留viewHolder的引用。
我建议您尝试这样的方法:
public class PhotoViewHolder extends RecyclerView.ViewHolder {
private TextView tvSongName;
public PhotoViewHolder(View v) {
super(v);
//initialize here views; ie
//this.tvSongName = v.findViewById(R.id.tvSongName);
}
public void initializeAsync(int position) {
Handler mHandler = new Handler();
new Thread(new Runnable() {
String songName, otherStuff;
@Override
public void run () {
// here we are async.
// Retrieve here your song informations, ie:
//object myRetrievedObject = getSongInfoBasedOnPositionSomeHow();
//songName = myRetrievedObject.retrievedSongName;
//otherStuff = myRetrievedObject.retrievedOtherStuffs;
mHandler.post(new Runnable() {
@Override
public void run () {
// make operation on UI
tvSongName.setText(songName);
//...
//...
}
});
}
}).start();
}
}然后这样叫它:
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
PhotoViewHolder vh = holder as PhotoViewHolder;
vh.initializeAsync(position);
}请考虑我在没有编译器的情况下写的,所以它可能不是完美的,让我知道在任何情况下。
希望这能有所帮助!
发布于 2018-11-22 14:39:22
我认为在activity类中再次加载arraylist之前,arraylist正在填充twice.so;要清除arraylist,然后在下一个tym.So中加载数据,每当您再次填充arraylist时,它将首先被清除,然后再次加载数据。
https://stackoverflow.com/questions/53413002
复制相似问题