代码之家  ›  专栏  ›  技术社区  ›  innomotion media

RecyclerView:在不阻塞UI线程的情况下重新加载数据

  •  0
  • innomotion media  · 技术社区  · 7 年前

    我正在开发一个应用程序,可以扫描你的手机中的MP3,然后将它们全部放入一个列表中,由 recyclerview 让你在它们之间滚动播放。

    回收服务 回收服务 ,但我不知道如何填充重新加载适配器,以便它不会一次全部重新加载,而是一步一步地重新加载。这就是ATM的外观:

    重新加载适配器:

    public class MySimpleItemLoader
    {
        public List<MP3object> mP3Objects { get; private set; }
        public bool IsBusy { get; set; }
        public int CurrentPageValue { get; set; }
        public bool CanLoadMoreItems { get; private set; }
    
        public MySimpleItemLoader(List<MP3object> mp3)
        {
            this.mP3Objects = mp3;
        }
    
        public void LoadMoreItems(int itemsPerPage)
        {
            IsBusy = true;
            for (int i = CurrentPageValue; i < CurrentPageValue + itemsPerPage; i++)
            {
                mP3Objects.Add(new MP3object() { AlbumName = string.Format("This is item {0:0000}", i) });
            }
    
            CanLoadMoreItems = true;
            CurrentPageValue = mP3Objects.Count;
            IsBusy = false;
        }
    
    
    }
    

    我的主要活动,在这里我加载一个包含所有mp3的列表(需要很长时间):

        private void PopulateMP3List(List<string> content)
        {
           mp3 = new List<MP3object>();        
           foreach (string obj in content)
           {
               WriteMetaDataToFileList(obj);        
           }
        }
    
    
    
        void WriteMetaDataToFileList(string obj)
        {
            reader.SetDataSource(obj);
    
            //Write Mp3 as object to global list
            MP3object ob = new MP3object();
            {
                if(reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle) != null)
                {
                    ob.SongName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle);
                }
                else
                {
                    ob.SongName = Resources.GetString(Resource.String.Unknown);
                }
    
                if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist) != null)
                {
                    ob.ArtistName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist);
                }
                else
                {
                    ob.ArtistName = Resources.GetString(Resource.String.Unknown);
                }
    
                if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum) != null)
                {
                    ob.AlbumName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum);
                }
                else
                {
                    ob.AlbumName = Resources.GetString(Resource.String.Unknown);
                }
    
                if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != null)
                {
                    ob.Year = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear);
                }
                else
                {
                    ob.Year = Resources.GetString(Resource.String.Unknown);
                }
    
                if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != null)
                {
                    ob.Year = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear);
                }
                else
                {
                    ob.Year = Resources.GetString(Resource.String.Unknown);
                }
    
                ob.Mp3Uri = obj; // can never be unknown!
    
                ob.DurationInSec = int.Parse(reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyDuration)) / 1000; // can never be unknown, div by 1000 to get sec not millis
            }
            mp3.Add(ob);
    
        }
    
        public List<string> ReturnPlayableMp3(bool sdCard)
        {
            List<string> res = new List<string>();
            string phyle;
            string path1 = null;
    
            if(sdCard) // get mp3 from SD card
            {
                string baseFolderPath = "";
    
                try
                {
                    bool getSDPath = true;
    
                    Context context = Application.Context;
                    Java.IO.File[] dirs = context.GetExternalFilesDirs(null);
    
                    foreach (Java.IO.File folder in dirs)
                    {
                        bool IsRemovable = Android.OS.Environment.InvokeIsExternalStorageRemovable(folder);
                        bool IsEmulated = Android.OS.Environment.InvokeIsExternalStorageEmulated(folder);
    
                        if (getSDPath ? IsRemovable && !IsEmulated : !IsRemovable && IsEmulated)
                            baseFolderPath = folder.Path;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("GetBaseFolderPath caused the following exception: {0}", ex);
                }
    
                string xy = baseFolderPath.Remove(18); // This is result after this, but this hard coded solution could be a problem on different phones.: "/storage/05B6-2226/Android/data/Media_Player.Media_Player/files"
    
                path1 = xy;
                // path to SD card and MUSIC "/storage/05B6-2226/"
            }
            else // get Mp3 from internal storage
            {
                    path1 = Android.OS.Environment.ExternalStorageDirectory.ToString();
            }
    
            var mp3Files = Directory.EnumerateFiles(path1, "*.mp3", SearchOption.AllDirectories);
    
            foreach (string currentFile in mp3Files)
            {
                phyle = currentFile;
                res.Add(phyle);
            }
    
            return res;
        }
    

    我该如何转换它,以便加载不在主活动中发生,而是在回收器视图重新加载适配器中需要它的地方发生?

    非常感谢:)

    1 回复  |  直到 7 年前
        1
  •  2
  •   2hamed    7 年前

    我想你不明白 RecyclerView 正确使用。这个 回收服务
    任何数据加载到 回收服务

    为了纠正这个错误,您需要将数据加载到 回收服务 的适配器,然后通知它投射更改。如果你有大量的数据需要很长时间来加载,你可以用较小的步骤来完成,并更新 每一步之后。举例来说,你在每一步100首歌中加载700首歌。

    val audioFiles = mutableListOf<String>()
    Observable.create{ e ->
        for{
            val offset = audioFiles.size
            // load your files here
            if(audioFiles.size % 100){
                e.onNext(offset)
            }
        }
        e.onComplete()
    }
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe{ offset ->
        mAdapter.notifyItemRangeInserted(offset, offset+100)
    }