В моем приложении фоновая задача должна получить медиафайл с телефона и показать его имя, исполнителя и обложку, если они доступны.
Выполнение в потоке пользовательского интерфейса приводило к тому, что приложение становилось слишком медленным, однако выполнение этой задачи в асинхронной задаче работает плавно, но иногда дает неверные результаты. Имена неверны, или изображение неверно. Иногда предметы удваиваются. Я записал это на пленку здесь:
https://www.youtube.com/watch?v=SVAvY6X5yr0.
Я действительно не знаю, что я делаю неправильно, но, похоже, что-то есть. Вот как все это выглядит:
private async Task SetContentAsync(PhotoViewHolder vh, int position)
{
string SongName = "";
string ArtistName = "";
Bitmap bitmap = null;
byte[] data = null;
RequestOptions requestOptions = new RequestOptions();
try
{
reader.SetDataSource(mp3Obj[position].Mp3Uri);
}
catch
{
Toast.MakeText(ctx, "ERROR 77s9", ToastLength.Short).Show();
}
await Task.Run(() => // cause problems with the reload
{
SongName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle);
ArtistName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist);
data = reader.GetEmbeddedPicture();
if (data != null)
{
try
{
bitmap = BitmapFactory.DecodeByteArray(data, 0, data.Length);
requestOptions.InvokeDiskCacheStrategy(DiskCacheStrategy.None);
requestOptions.SkipMemoryCache(false);
requestOptions.CircleCrop();
requestOptions.CenterInside();
requestOptions.FitCenter();
ConvertBitmapToBackground(bitmap, vh, data); // Set As Backgorund, blurry and black ( just sets the variable)
}
catch
{
Toast.MakeText(ctx, "ERROR 034c", ToastLength.Short).Show();
}
}
});
((Activity)ctx).RunOnUiThread(() =>
{
vh.SongName.SetTypeface(tf, TypefaceStyle.Normal);
vh.AristName.SetTypeface(tf, TypefaceStyle.Normal);
vh.SongName.Text = SongName;
vh.AristName.Text = ArtistName;
try
{
if (data != null)
{
Glide
.With(ctx)
.Load(data)
.Apply(requestOptions)
.Into(vh.CoverArt);
}
else // because recycler items inherit their stuff and if it is altered it just shows views were there shouldnt be any ...
{
vh.CoverArt.SetImageResource(Resource.Drawable.btn_musicalnote);
vh.dr = null;
}
}
catch {
Toast.MakeText(ctx, "ERROR 034c", ToastLength.Short).Show();
}
});
}
Вкратце: я устанавливаю все переменные, которые мне нужны для одного элемента, затем заполняю их внутри асинхронной задачи содержимым, а затем устанавливаю содержимое в потоке пользовательского интерфейса.
Это плохо?
Спасибо
EDIT:
Это функция инициализации представления переработчика:
private void InitRecView()
{
if (ap.getFirstStart())
{
ShowTutorial(1);
ap.saveFirstStart(false);
}
// Instantiate the adapter and pass in its data source:
ImageView lnBg = (ImageView)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(50);
mRecyclerView.DrawingCacheEnabled = true;
mRecyclerView.DrawingCacheQuality = DrawingCacheQuality.High;
mLayoutManager = new PreCachingLayoutManager(this);
mLayoutManager.ItemPrefetchEnabled = true;
mRecyclerView.SetLayoutManager(mLayoutManager);
А это PhotoViewHolder:
public PhotoViewHolder(View itemView, List<MP3objectSmall> mp3Obj, Activity_Player act, MediaMetadataRetriever reader, DataBase db, List<SeekObj> seekObj, AudioManager audioManager, ImageView 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);
};
}