-1

在我的应用程序中,我使用了 RV。这是它的重载适配器:

    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;
        RequestOptions requestOptions = null;

        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 = new RequestOptions();
                    requestOptions.InvokeDiskCacheStrategy(DiskCacheStrategy.None);
                   // requestOptions.SkipMemoryCache(true);
                    requestOptions.CircleCrop();
                    requestOptions.CenterInside();
                    requestOptions.FitCenter();
                    requestOptions.OptionalCircleCrop();


                    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 shit 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();
             }

        });


    }

如您所见,数据被解码的部分过去是在异步方法中,不会阻塞 UI 线程。但是,这会导致加载时出现问题。在繁重的工作下,物品的信息错误,物品翻倍,有时甚至被绊倒。通过删除异步任务并将其全部同步完成,问题得到了解决。但是,这使整个应用程序变得更加滞后。

如何在 RV 中正确使用 asnyc 任务,而不会弄乱项目?

4

1 回答 1

0

你的问题在这里:

private async void SetContent(PhotoViewHolder vh, int position)
{
  await SetContentAsync(vh, position);
}

问题async void之一是调用代码不知道该方法何时完成。就您的 RV 所知,它要求您的代码设置内容,并返回代码,因此它认为它具有它将获得的任何内容。

这是每个 UI 框架的一个基本问题:当计算机/设备需要显示某些内容时,它需要立即显示。要显示的数据必须同步可用。

那么,我们如何协调这与从 I/O 加载数据的必要性以及 I/O 应该是异步的概念?

一种常见的模式是(同步)加载占位符数据。“正在加载...”消息或微调器或其他任何内容。相同的代码也开始异步加载真实数据。当数据到达时(即 I/O 完成),UI 会更新(同步)以显示真实数据。

您可能会发现我关于异步数据绑定的文章很有用。它采用占位符数据模式并将其应用于数据绑定 UI 框架(WPF、Xamarin 等)。我认为您使用的是较低级别的 Android UI API,因此代码不会直接相关,但您应该能够做类似的事情。生成的代码将比使用数据绑定更冗长,但应该应用相同的概念和模式。

于 2019-02-08T18:52:23.730 回答