RecyclerView:大量计算导致 RV 中的文件命名错误或翻倍(带视频)

创新媒体

很长一段时间以来,我在 recyclerview 上一遍又一遍地遇到同样的问题。

简短版本:当 RV 快速滚动并且需要在短时间内进行大量计算时,它有时会“跳过”代码行。

我在这个 10 秒的视频中录制了这种行为:

https://www.youtube.com/watch?v=SVAvY6X5yr0

注意我是如何向下滚动到歌曲文件“Supreme”的。据说是 Billy Talent 出品,但事实并非如此。它实际上是罗比威廉姆斯的作品。RV 确实知道这一点。当我向下滚动直到视图离开屏幕然后向上滚动时,它似乎已经“纠正”了自己。这首歌现在由罗比威廉姆斯演唱。此外,它左侧不正确的专辑封面现在也已修复并显示标准图像,因为我的手机上从来没有专辑封面。

当滚动变得非常激烈时,结果会越来越糟。有时项目会翻倍甚至三倍,而当点击正确的歌曲时正在播放。

同样有趣的是,RV 选择了正确的歌曲名称:“Supreme”,但却弄乱了专辑封面和艺术家姓名。

另一件值得注意的事情:每张专辑封面都应该被裁剪成同一个圆圈。然而,“至尊”的不正确专辑封面艺术被简单地忽略并保留为矩形形式。再说一遍:就好像 RV 只是“跳过”代码行一样。

好吧,说起来:这基本上就是整个事情:

从 OnCreate() 调用的 Init 函数:

    private void InitRecView()
    {

        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 class PhotoViewHolder : RecyclerView.ViewHolder
    {
        public ImageView Image { get; private set; }
        public TextView SongName { get; private set; }
        public LinearLayout lnContainer { get; private set; }
        public TextView AristName { get; private set; }
        public ImageButton CoverArt { get; private set; }
        public Drawable dr { get; set; }


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

        private void ClickEvent(int position, string artist, string song, ImageView CoverArt, ImageView lnBackground)
        {

            if (PhotoAlbumAdapter.NewSongUri != null)
            {
                PhotoAlbumAdapter.OldSongUri = PhotoAlbumAdapter.NewSongUri;
            }

            PhotoAlbumAdapter.NewSongUri = Android.Net.Uri.Parse(mp3Obj[position].Mp3Uri);

            if (!FirstStart) // dont save the very first uri, only get it for playing 
            {
                ObjectToBeSaved = WriteMetaDataToFileList(PhotoAlbumAdapter.OldSongUri.ToString());
            }

            Activity_Player.CurrentSongObject = WriteMetaDataToFileList(PhotoAlbumAdapter.NewSongUri.ToString());
            Activity_Player.txt_CurrentSong.Text = song;
            Activity_Player.txt_CurrentArtist.Text = artist;

            PlayMusic(PhotoAlbumAdapter.NewSongUri);

            FirstStart = false;

            Activity_Player.SetBackgroundToHeader(dr, lnBg, Activity_Player.btn_Settings, ctx);

        }

还有可能是最重要的类 PhotoAlbumAdapter:

 public class PhotoAlbumAdapter : RecyclerView.Adapter
        {
            public List<MP3objectSmall> mp3Obj;
            Context ctx;
            Activity_Player act;
            MediaMetadataRetriever reader;
            DataBase db;
            List<SeekObj> seekObj;
            Typeface tf;
            AudioManager audioManager;
            ImageView lnBg;
            LinearLayout ln;

            public static Android.Net.Uri NewSongUri = null;
            public static Android.Net.Uri OldSongUri = null;

            public PhotoAlbumAdapter(List<MP3objectSmall> mp3Obj, Context ctx, DataBase db, List<SeekObj> seekObj, AudioManager audioManager, Activity_Player act, ImageView lnBg)
            {
                this.lnBg = lnBg;
                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, lnBg, ctx);

                ln = itemView.FindViewById<LinearLayout>(Resource.Id.linlay_album_art);
                ln.LayoutParameters.Height = ctx.Resources.DisplayMetrics.HeightPixels / 10;
                ln.RequestLayout();

                return vh;
            }

            public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
            {
                PhotoViewHolder vh = holder as PhotoViewHolder;
                SetContent(vh, position);

            }

            public override void OnViewRecycled(Java.Lang.Object holder)
            {
                base.OnViewRecycled(holder);

            }

            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 { }


                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 { }
                    }

                });



                ((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 { }

                });


            }

            public override int ItemCount
            {

                get
                {
                    if (mp3Obj != null)
                    {
                        return mp3Obj.Count();
                    }
                    else
                        return 0;
                }
            }    

        }

        }

在 SetContentAsync() 中,RV 决定将什么项目放在哪里。这是我清楚地说明它应该做什么的地方,这是我认为代码行被跳过的地方。

我真的,真的需要帮助。我认为我做的一切都是正确的 - 谁能解释这种奇怪的行为?

非常感谢!

库夫斯

我会说异步处理可能是罪魁祸首。有时,您可能会在较早启动的迭代之前完成一次迭代,这实质上允许较早的迭代覆盖后来的“正确”值。

为了解决这个问题,我会在启动异步操作之前在每个持有者中放置一个 UUID 标志,并且只有在异步操作完成后标志匹配时才允许更新视图。这将确保“陈旧”操作无法更新 UI。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在 JavaScript 中响应大量计算的代码

来自分类Dev

除以零警告导致常量计算中的错误值

来自分类Dev

打印功能中的模量计算?

来自分类Dev

打印功能中的模量计算?

来自分类Dev

最大数量计算错误

来自分类Dev

使用变量计算data.table中的列

来自分类Dev

根据R中的向量计算差异矩阵

来自分类Dev

根据LeafletJS中的给定数量计算半径

来自分类Dev

Julia中的数组/张量计算效率

来自分类Dev

R中的excel模拟增量计算

来自分类Dev

关于汇总报告的jmeter中的吞吐量计算

来自分类Dev

React JS异步大量计算

来自分类Dev

在Flutter / Dart中解析JSON:<RK,RV>()=> Map <RK,RV>,NoSuchMethodError-(数组问题?)

来自分类Dev

ValueError:参数scipy rv_continuous中的域错误

来自分类Dev

批量计算所有文件,但排除特定文件夹中的文件

来自分类Dev

批量计算所有文件,但排除特定文件夹中的文件

来自分类Dev

运行大量计算使我的计算机滞后

来自分类Dev

Python中的特征值和向量计算错误

来自分类Dev

集更新或大量计算的Clojure性能

来自分类Dev

在进行大量计算时,如何使屏幕停止冻结?

来自分类Dev

C#模式或设计,可进行大量计算

来自分类Dev

从磁盘偏移量计算Win PE文件任何部分的内存偏移量

来自分类Dev

从磁盘偏移量计算Win PE文件的任何部分的内存偏移量

来自分类Dev

如何根据R中的U和V风分量计算风向

来自分类Dev

如何使用R中的2个组变量计算特定范围的统计信息?

来自分类Dev

如何在TensorFlow中批量计算基于元素的条件?

来自分类Dev

ns3中udp连接的吞吐量计算

来自分类Dev

如何通过R中的变量计算疾病患病率

来自分类Dev

如何从PromQL(Prometheus)中的范围向量计算阈值指标

Related 相关文章

  1. 1

    在 JavaScript 中响应大量计算的代码

  2. 2

    除以零警告导致常量计算中的错误值

  3. 3

    打印功能中的模量计算?

  4. 4

    打印功能中的模量计算?

  5. 5

    最大数量计算错误

  6. 6

    使用变量计算data.table中的列

  7. 7

    根据R中的向量计算差异矩阵

  8. 8

    根据LeafletJS中的给定数量计算半径

  9. 9

    Julia中的数组/张量计算效率

  10. 10

    R中的excel模拟增量计算

  11. 11

    关于汇总报告的jmeter中的吞吐量计算

  12. 12

    React JS异步大量计算

  13. 13

    在Flutter / Dart中解析JSON:<RK,RV>()=> Map <RK,RV>,NoSuchMethodError-(数组问题?)

  14. 14

    ValueError:参数scipy rv_continuous中的域错误

  15. 15

    批量计算所有文件,但排除特定文件夹中的文件

  16. 16

    批量计算所有文件,但排除特定文件夹中的文件

  17. 17

    运行大量计算使我的计算机滞后

  18. 18

    Python中的特征值和向量计算错误

  19. 19

    集更新或大量计算的Clojure性能

  20. 20

    在进行大量计算时,如何使屏幕停止冻结?

  21. 21

    C#模式或设计,可进行大量计算

  22. 22

    从磁盘偏移量计算Win PE文件任何部分的内存偏移量

  23. 23

    从磁盘偏移量计算Win PE文件的任何部分的内存偏移量

  24. 24

    如何根据R中的U和V风分量计算风向

  25. 25

    如何使用R中的2个组变量计算特定范围的统计信息?

  26. 26

    如何在TensorFlow中批量计算基于元素的条件?

  27. 27

    ns3中udp连接的吞吐量计算

  28. 28

    如何通过R中的变量计算疾病患病率

  29. 29

    如何从PromQL(Prometheus)中的范围向量计算阈值指标

热门标签

归档