Заполнение списка из асинхронной задачи дает странные результаты - PullRequest
0 голосов
/ 14 января 2019

В моем приложении фоновая задача должна получить медиафайл с телефона и показать его имя, исполнителя и обложку, если они доступны.

Выполнение в потоке пользовательского интерфейса приводило к тому, что приложение становилось слишком медленным, однако выполнение этой задачи в асинхронной задаче работает плавно, но иногда дает неверные результаты. Имена неверны, или изображение неверно. Иногда предметы удваиваются. Я записал это на пленку здесь:

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);
        };
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...