AsyncTask导致重新加载问题(项目重复,数据错误等),但是在UI上运行太慢

时间:2019-01-09 11:36:35

标签: android android-recyclerview

在我的应用中,我使用了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任务而不弄乱项目?

1 个答案:

答案 0 :(得分:0)

您的问题在这里:

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

problems with async void之一是调用代码不知道该方法何时完成。据您的RV所知,它要求您的代码设置内容,然后返回代码,因此它确定它具有要获取的任何内容。

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

那么,我们如何将其与从I / O加载数据的必要性以及I / O应该异步的观念相协调呢?

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

您可能会发现我的article on asynchronous data binding有用。它采用Placeholder Data模式并将其应用于数据绑定UI框架(WPF,Xamarin等)。我认为您使用的是较低级别的Android UI API,因此代码不会直接相关,但是您应该可以执行类似的操作。生成的代码将比使用数据绑定更为冗长,但是应该应用相同的概念和模式。